Usare grep nell'istruzione condizionale in bash


22

Sono ancora molto nuovo nello scripting in bash, e sto solo provando alcune cose che pensavo fossero cose basilari. Voglio eseguire DDNS che si aggiorna dal mio server che esegue Ubuntu 14.04.

Prendendo in prestito un po 'di codice da dnsimple, questo è quello che ho finora:

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

L'idea è che funziona ogni 5 minuti, che sto lavorando usando un cronjob. Voglio quindi controllare l'output del ricciolo per vedere se lo stato è "200" o altro. Se è qualcos'altro, allora voglio salvare l'output in un file.

Quello che non riesco a far funzionare è la ifdichiarazione. A quanto mi risulta, il -qsul grepcomando fornirà un codice di uscita per la ifdichiarazione. Tuttavia non riesco a farlo funzionare. Dove ho sbagliato?


Lo script funziona se si rimuove il ifsegno di spunta e si fa sempre eco al file di registro? dnssimple mostra un $LOGINprima $TOKEN, ma ti manca. Forse questo sta causando il fallimento delle cose?
Mikel,

1
L'ho leggermente modificato. Sto usando un DNSimple-Domain-Tokenche non ha bisogno della LOGINvariabile.
CircularRecursion

se fossi in te, lo farei solo quando l'interfaccia di rete Internet si alza piuttosto che ogni 5 minuti da cron. o, almeno, cache "$ IP" in un file da qualche parte (forse /var/tmp/icanhazip) e se non è cambiato dall'ultima esecuzione, exit 0prima di fare qualsiasi altra cosa. non è necessario aggiornare la voce DDNS ogni 5 minuti, solo quando il tuo indirizzo IP cambia.
CAS

Buona idea - Lavorerò per aggiungerlo.
CircularRecursion,

Risposte:


28

Ci sei quasi. Ometti il ​​punto esclamativo:

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

Risultato:

MATCH

La ifcondizione è soddisfatta se grep ritorna con il codice di uscita 0 (che significa una corrispondenza). Il !punto esclamativo annullerà questo.


5

Dato che stai già usando bash, potresti tenerlo interno a bash:

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

Esecuzioni campione:

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


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

3

Questa non è una risposta alla tua domanda, ma alcuni suggerimenti da un collega scripter:

  • Usa $()invece di backtick, non usarli entrambi
  • ifDichiarazioni condizionali di rientro
  • Rimuovere l'utilizzo non necessario di $()

La coerenza e le semplici regole ti aiuteranno a eseguire il debug e a mantenere gli script a lungo termine ...

#!/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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.