Używanie grep w instrukcji warunkowej w bash

22

Nadal jestem nowy w skryptowaniu w bash i próbuję tylko kilku rzeczy, które moim zdaniem będą podstawowymi rzeczami. Chcę uruchomić DDNS, który aktualizuje z mojego serwera z Ubuntu 14.04.

Pożyczając trochę kodu z dnsimple, oto co mam do tej pory:

#!/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

Chodzi o to, że działa co 5 minut, co mam pracy przy użyciu cronjob. Następnie chcę sprawdzić wynik curl, aby zobaczyć, czy stan to „200” lub inny. Jeśli jest to coś innego, chcę zapisać dane wyjściowe w pliku.

To, czego nie mogę uruchomić, to ifoświadczenie. Jak rozumiem, -qna greppolecenia zapewni kod wyjścia dla ifstwierdzenia. Jednak nie wydaje mi się, żeby działało. Gdzie popełniłem błąd?

CircularRecursion
źródło
Czy Twój skrypt działa, jeśli usuniesz ifzaznaczenie i zawsze echo pliku dziennika? dnssimple pokazuje $LOGINwcześniej $TOKEN, ale tego brakuje. Może to powoduje niepowodzenia?
Mikel
1
Lekko to zmodyfikowałem. Używam, DNSimple-Domain-Tokenktóry nie potrzebuje LOGINzmiennej.
CircularRecursion
gdybym był tobą, uruchomiłbym to tylko wtedy, gdy interfejs sieci internetowej idzie w górę, a nie co 5 minut od crona. lub przynajmniej buforuj „$ IP” w jakimś pliku (być może /var/tmp/icanhazip) i jeśli nie zmieniło się od ostatniego uruchomienia, exit 0zanim zrobisz cokolwiek innego. nie musisz aktualizować wpisu DDNS co 5 minut, tylko przy zmianie adresu IP.
cas
Dobry pomysł - będę pracować nad dodaniem tego.
CircularRecursion

Odpowiedzi:

28

Jesteś prawie na miejscu. Po prostu pomiń wykrzyknik:

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

Wynik:

MATCH

ifWarunek jest spełniony, jeżeli grep powraca z kodem wyjściowym 0 (co oznacza meczu). !Wykrzyknik będzie negować tego.

Guido
źródło
5

Ponieważ już korzystasz z bash, możesz zachować wewnętrzną wersję bash:

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

Przykładowe przebiegi:

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


OUTPUT='something good (Status: 200)'
[[ $OUTPUT =~ (Status:[[:space:]]200) ]] && echo match
match
Jeff Schaller
źródło
3

To nie jest odpowiedź na twoje pytanie, ale kilka sugestii innego autora:

  • Użyj $()zamiast tyknięć, nie używaj ich obu
  • Wcięte ifzdania warunkowe
  • Usuń niepotrzebne użycie $()

Spójne i proste reguły pomogą ci debugować i utrzymywać skrypty na dłuższą metę ...

#!/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
źródło