Usando grep na instrução condicional no bash


18

Eu ainda sou muito novo em scripts no bash, e apenas tentando algumas coisas que eu pensava serem coisas básicas. Quero executar o DDNS que atualiza do meu servidor executando o Ubuntu 14.04.

Tomando emprestado algum código do dnsimple, é isso que tenho até agora:

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

A idéia é que seja executado a cada 5 minutos, o que eu estou trabalhando usando um cronjob. Desejo, então, verificar a saída do curl para ver se o status é "200" ou outro. Se for outra coisa, quero salvar a saída em um arquivo.

O que não consigo trabalhar é a ifafirmação. Pelo que entendi, o -qno grepcomando irá fornecer um código de saída para a ifdeclaração. No entanto, eu não consigo fazê-lo funcionar. Onde eu errei?


Seu script funciona se você remover a ifverificação e sempre ecoar no arquivo de log? O dnssimple mostra um $LOGINantes $TOKEN, mas você está sentindo falta disso. Talvez isso esteja causando falhas nas coisas?
Mikel

1
Eu o modifiquei levemente. Estou usando um DNSimple-Domain-Tokenque não precisa da LOGINvariável.
CircularRecursion

se eu fosse você, executaria isso apenas quando a interface da rede da Internet subir, e não a cada 5 minutos do cron. ou, pelo menos, armazene em cache "$ IP" em um arquivo em algum lugar (talvez /var/tmp/icanhazip) e, se não tiver sido alterado desde a última execução, exit 0antes de fazer qualquer outra coisa. você não precisa atualizar sua entrada DDNS a cada 5 minutos, apenas quando o seu endereço IP for alterado.
cas

Boa ideia - vou trabalhar adicionando isso.
CircularRecursion

Respostas:


24

Você está quase lá. Apenas omita o ponto de exclamação:

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

Resultado:

MATCH

A ifcondição será atendida se grep retornar com o código de saída 0 (o que significa uma correspondência). O !ponto de exclamação negará isso.


5

Como você já está usando o bash, você pode mantê-lo interno para o bash:

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

Amostras de execuções:

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


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

3

Esta não é uma resposta para sua pergunta, mas poucas sugestões de um colega de script:

  • Use em $()vez de backticks, não use os dois
  • Indentar ifinstruções condicionais
  • Remova o uso desnecessário de $()

Regras consistentes e simples ajudarão você a depurar e manter scripts a longo prazo ...

#!/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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.