Usando grep en la declaración condicional en bash

22

Todavía soy muy nuevo en las secuencias de comandos en bash, y solo intento algunas que pensé que serían cosas básicas. Quiero ejecutar DDNS que se actualiza desde mi servidor que ejecuta Ubuntu 14.04.

Tomando prestado algún código de dnsimple, esto es lo que tengo hasta ahora:

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

La idea es que se ejecuta cada 5 minutos, que tengo trabajando usando un cronjob. Luego quiero verificar la salida del rizo para ver si el estado es "200" u otro. Si es otra cosa, entonces quiero guardar la salida en un archivo.

Lo que no puedo hacer funcionar es la ifdeclaración. Como yo lo entiendo, la -qdel grepcomando proporcionará un código de salida para el ifcomunicado. Sin embargo, parece que no puedo hacer que funcione. ¿Dónde me he equivocado?

Recursividad circular
fuente
¿Funciona su script si elimina la ifverificación y siempre hace eco en el archivo de registro? dnssimple muestra un $LOGINantes $TOKEN, pero te lo estás perdiendo. ¿Quizás eso está causando que las cosas fallen?
Mikel
1
Lo he modificado un poco. Estoy usando un DNSimple-Domain-Tokenque no necesita la LOGINvariable.
CircularRecursion
si fuera usted, lo ejecutaría solo cuando la interfaz de red de Internet se active en lugar de cada 5 minutos desde cron. o, al menos, guarde en caché "$ IP" en un archivo en algún lugar (tal vez /var/tmp/icanhazip) y si no ha cambiado desde la última ejecución, exit 0antes de hacer cualquier otra cosa. no necesita actualizar su entrada DDNS cada 5 minutos, solo cuando cambia su dirección IP.
cas
Buena idea, trabajaré para agregar eso.
CircularRecursion

Respuestas:

28

Ya casi estás ahí. Simplemente omita el signo de exclamación:

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

Resultado:

MATCH

La ifcondición se cumple si grep regresa con el código de salida 0 (que significa una coincidencia). El !signo de exclamación negará esto.

Guido
fuente
5

Como ya estás usando bash, puedes mantenerlo interno para bash:

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

Ejecuciones de muestra:

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


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

Esta no es una respuesta a su pregunta, sino algunas sugerencias de un compañero scripter:

  • Use en $()lugar de backticks, no los use a ambos
  • Sangrar ifdeclaraciones condicionales
  • Eliminar el uso innecesario de $()

La coherencia y las reglas simples lo ayudarán a depurar y mantener los scripts a largo plazo ...

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