Um operador "and" para uma declaração "if" no Bash

168

Estou tentando criar um script Bash simples para verificar se o site está inoperante e, por algum motivo, o operador "and" não funciona:

#!/usr/bin/env bash

WEBSITE=domain.com
SUBJECT="$WEBSITE DOWN!"
EMAILID="[email protected]"
STATUS=$(curl -sI $WEBSITE | awk '/HTTP\/1.1/ { print $2 }')
STRING=$(curl -s $WEBSITE | grep -o "string_to_search")
VALUE="string_to_search"

if [ $STATUS -ne 200 ] && [[ "$STRING" != "$VALUE" ]]; then
    echo "Website: $WEBSITE is down, status code: '$STATUS' - $(date)" | mail -s "$SUBJECT" $EMAILID
fi

O operador "-a" também não funciona:

if [ $STATUS -ne 200 ] -a [[ "$STRING" != "$VALUE" ]]

Você também pode aconselhar quando usar:

  • colchetes simples e duplos
  • parêntese

?

HTF
fonte
3
Poderia, por favor, ser mais preciso sobre o que "não funciona"? Você tem uma mensagem de erro específica ou simplesmente não fornece a saída esperada?
Julien Vivenot
Eu estava realmente recebendo "operador unário esperado" de modo que parece citando ajuda
HTF
-atem duplicidade. Quando usado com o testcomando de estilo de shell Bourne , também conhecido como [, significa and. Quando usado como uma expressão condicional , ele está testando para ver se existe um arquivo. Sim, é confuso, é melhor evitar.
cdarke

Respostas:

254

O que você tem deve funcionar, a menos que ${STATUS}esteja vazio. Provavelmente seria melhor fazer:

if ! [ "${STATUS}" -eq 200 ] 2> /dev/null && [ "${STRING}" != "${VALUE}" ]; then

ou

if [ "${STATUS}" != 200 ] && [ "${STRING}" != "${VALUE}" ]; then

É difícil dizer, pois você não nos mostrou exatamente o que está acontecendo de errado com seu script.

Opinião pessoal: nunca use [[. Ele suprime mensagens de erro importantes e não é portátil para diferentes shells.

William Pursell
fonte
2
Se STATUSestiver vazio, o código de @HTF falharia -ne: unary operator expected. No seu caso, ele falhará integer expression expected, não é?
Julien Vivenot
1
Eu entendi aquilo. Mas você destaca o problema que $STATUSpode estar vazio e sugere uma solução (citando-o). Sua solução ainda falha com um vazio STATUS, é isso que eu quis dizer.
Julien Vivenot
1
@jvivenot Você tem razão. (Minha resposta ao seu comentário foi feita antes de você o editar, quando seu comentário dizia apenas "o código ... teria falhado". Uma solução simples é a de usar ${STATUS:-0". Será editada.
William Pursell
Desculpe, sua edição ainda não funciona. Por exemplo: STATUS=; [ $STATUS -ne 13 ] 2>/dev/null && echo foonão gera foo, mesmo que deva (vazio é diferente de 13). O que você sugeriu primeiro ${STATUS:-0}parece muito melhor.
Julien Vivenot
@jvivenot O uso ${STATUS:-0}falhará se STATUS=foo, mas ! [ "$STATUS" -eq 200 ] 2> /dev/null && echo foofuncionar. IMO, no entanto, é melhor evitar -eqe usar !=.
William Pursell #
28

Tente o seguinte:

if [ $STATUS -ne 200 -a "$STRING" != "$VALUE" ]; then
BrenanK
fonte
trabalhou para mim. Acho que pode haver mais de uma maneira, mas estou satisfeito com isso por enquanto.
Kushal Ashok
27

Tente o seguinte:

if [ ${STATUS} -ne 100 -a "${STRING}" = "${VALUE}" ]

ou

if [ ${STATUS} -ne 100 ] && [ "${STRING}" = "${VALUE}" ]
AnshBikram
fonte
mais para o exemplo mais limpo
Pawel Cioch
12

Citar:

O operador "-a" também não funciona:

se [$ STATUS -ne 200] -a [["$ STRING"! = "$ VALUE"]]

Para uma explicação mais elaborada: [e ]não são palavras reservadas no Bash. A ifpalavra-chave introduz um condicional a ser avaliado por um trabalho (o condicional é verdadeiro se o valor de retorno do trabalho for 0falso ou não).

Para testes triviais, existe o testprograma ( man test).

Como alguns consideram linhas como if test -f filename; then foo bar; fietc. irritantes, na maioria dos sistemas, você encontra um programa chamado [que na verdade é apenas um link simbólico para o testprograma. Quando testé chamado como [, você deve adicionar ]como o último argumento posicional.

Então if test -f filenameé basicamente o mesmo (em termos de processos gerados) que if [ -f filename ]. Nos dois casos, o testprograma será iniciado e os dois processos deverão se comportar de forma idêntica.

Aqui está o seu erro: if [ $STATUS -ne 200 ] -a [[ "$STRING" != "$VALUE" ]]analisará if+ algum trabalho, o trabalho sendo tudo, exceto o ifpróprio. O trabalho é apenas um comando simples (o Bash fala por algo que resulta em um único processo), o que significa que a primeira palavra ( [) é o comando e o restante, seus argumentos posicionais. Existem argumentos restantes após o primeiro] .

Também não [[é , de fato, uma palavra-chave do Bash, mas, neste caso, é analisada apenas como um argumento de comando normal, porque não está na frente do comando.

Jo So
fonte