Menggunakan grep dalam pernyataan kondisional di bash

18

Saya masih sangat baru dalam scripting di bash, dan hanya mencoba beberapa hal yang saya pikir akan menjadi hal mendasar. Saya ingin menjalankan DDNS yang diperbarui dari server saya yang menjalankan Ubuntu 14.04.

Meminjam beberapa kode dari dnsimple, inilah yang saya miliki sejauh ini:

#!/bin/bash

LOGIN="email"
TOKEN="token"
DOMAIN_ID="domain"
RECORD_ID="record"
IP=`curl -s http://icanhazip.com/`

OUTPUT=`
curl -H "Accept: application/json" \
     -H "Content-Type: application/json" \
     -H "X-DNSimple-Domain-Token: $TOKEN" \
     -X "PUT" \
     -i "https://api.dnsimple.com/v1/domains/$DOMAIN_ID/records/$RECORD_ID" \
     -d "{\"record\":{\"content\":\"$IP\"}}"`

if ! echo "$OUTPUT" | grep -q "(Status:\s200)"; then

echo "match"

$(echo "$OUTPUT" | grep -oP '(?<="message":")(.[^"]*)' >> /home/ddns/ddns.log)
$(echo "$OUTPUT"| grep -P '(Status:\s[0-9]{3}\s)' >> /home/ddns/ddns.log)

fi

Idenya adalah itu berjalan setiap 5 menit, yang saya kerjakan menggunakan cronjob. Saya kemudian ingin memeriksa output dari ikal untuk melihat apakah statusnya "200" atau lainnya. Jika itu adalah sesuatu yang lain, maka saya ingin menyimpan output ke file.

Yang tidak bisa saya dapatkan adalah ifpernyataannya. Seperti yang saya pahami, -qpada grepperintah akan memberikan kode keluar untuk ifpernyataan. Namun sepertinya saya tidak bisa membuatnya bekerja. Di mana saya salah?

Perulangan Circular
sumber
Apakah skrip Anda berfungsi jika Anda menghapus ifcentang dan selalu menggema ke file log? dnssimple menunjukkan $LOGINsebelumnya $TOKEN, tetapi Anda melewatkannya. Mungkin itu yang menyebabkan semuanya gagal?
Mikel
1
Saya sudah sedikit memodifikasinya. Saya menggunakan DNSimple-Domain-Tokenyang tidak perlu LOGINvariabel.
CircularRecursion
jika saya jadi Anda, saya akan menjalankan ini hanya ketika antarmuka jaringan internet naik daripada setiap 5 menit dari cron. atau, paling tidak, cache "$ IP" dalam file di suatu tempat (mungkin /var/tmp/icanhazip) dan jika itu tidak berubah sejak dijalankan terakhir, exit 0sebelum melakukan hal lain. Anda tidak perlu memperbarui entri DDNS Anda setiap 5 menit, hanya ketika alamat IP Anda berubah.
cas
Ide bagus - saya akan berusaha menambahkannya.
CircularRecursion

Jawaban:

24

Kamu hampir sampai. Hapus saja tanda seru:

OUTPUT='blah blah (Status: 200)'
if echo "$OUTPUT" | grep -q "(Status:\s200)"; then
    echo "MATCH"
fi

Hasil:

MATCH

The ifkondisi terpenuhi jika kembali grep dengan kode keluar 0 (yang berarti pertandingan). Tanda !seru akan meniadakan ini.

Guido
sumber
5

Karena Anda sudah menggunakan bash, Anda bisa membuatnya internal untuk bash:

if [[ $OUTPUT =~ (Status:[[:space:]]200) ]]; then
  echo match
fi

Sampel berjalan:

OUTPUT='something bogus'
[[ $OUTPUT =~ (Status:[[:space:]]200) ]] && echo match


OUTPUT='something good (Status: 200)'
[[ $OUTPUT =~ (Status:[[:space:]]200) ]] && echo match
match
Jeff Schaller
sumber
3

Ini bukan jawaban untuk pertanyaan Anda, tetapi beberapa saran dari sesama penulis skenario:

  • Gunakan $()daripada backticks, jangan gunakan keduanya
  • Indentasikan ifpernyataan bersyarat
  • Hapus penggunaan yang tidak perlu dari $()

Konsistensi dan aturan sederhana akan membantu Anda men-debug dan memelihara skrip dalam jangka panjang ...

#!/bin/bash

LOGIN="email"
TOKEN="token"
DOMAIN_ID="domain"
RECORD_ID="record"
IP=$(curl -s http://icanhazip.com/)

OUTPUT=$(
curl -H "Accept: application/json" \
    -H "Content-Type: application/json" \
    -H "X-DNSimple-Domain-Token: $TOKEN" \
    -X "PUT" \
    -i "https://api.dnsimple.com/v1/domains/$DOMAIN_ID/records/$RECORD_ID" \
    -d "{\"record\":{\"content\":\"$IP\"}}"
)

if ! echo "$OUTPUT" | grep -q "(Status:\s200)"; then
    echo "match"
    echo "$OUTPUT" | grep -oP '(?<="message":")(.[^"]*)' >> /home/ddns/ddns.log
    echo "$OUTPUT"| grep -P '(Status:\s[0-9]{3}\s)' >> /home/ddns/ddns.log
fi
Vikyboss
sumber