Un operatore "e" per un'istruzione "if" in Bash


168

Sto cercando di creare un semplice script Bash per verificare se il sito Web non è attivo e per qualche motivo l'operatore "e" non funziona:

#!/usr/bin/env bash

WEBSITE=domain.com
SUBJECT="$WEBSITE DOWN!"
EMAILID="an@email.com"
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

Anche l'operatore "-a" non funziona:

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

Potresti anche avvisare quando usare:

  • parentesi quadre singole e doppie
  • parentesi

?


3
Potresti per favore essere più preciso su ciò che "non funziona"? Hai un messaggio di errore specifico o semplicemente non fornisce l'output previsto?
Julien Vivenot,

In realtà stavo ricevendo "l'operatore unario previsto", quindi sembra che la citazione aiuti
HTF

-aha duplicità. Se usato con il testcomando stile shell Bourne , aka [, significa and. Se usato come espressione condizionale , sta testando se esiste un file. Sì, è confuso, meglio evitare.
cdarke,

Risposte:


254

Quello che hai dovrebbe funzionare, a meno che non ${STATUS}sia vuoto. Probabilmente sarebbe meglio fare:

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

o

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

È difficile da dire, dal momento che non ci hai mostrato esattamente cosa non va nella tua sceneggiatura.

Opinione personale: non usare mai [[. Sopprime importanti messaggi di errore e non è portabile su diverse shell.


2
Se STATUSè vuoto, il codice da @HTF non sarebbe riuscito -ne: unary operator expected. Nel tuo caso, non funzionerà integer expression expected, vero?
Julien Vivenot,

1
Lo capisco. Ma evidenzi il problema che $STATUSpotrebbe essere vuoto e suggerisci una soluzione (citandola). La tua soluzione fallisce ancora con un vuoto STATUS, questo è tutto ciò che intendevo.
Julien Vivenot,

1
@jvivenot Hai ragione. (La mia risposta al tuo commento è stata fatta prima che tu modificassi il tuo commento, quando il tuo commento si limitava a leggere "il codice ... sarebbe fallito". Una soluzione semplice è quella di utilizzare ${STATUS:-0". Modificherà.
William Pursell

Siamo spiacenti, la modifica non funziona ancora. Ad esempio: STATUS=; [ $STATUS -ne 13 ] 2>/dev/null && echo foonon emette foo, anche se dovrebbe (vuoto è diverso da 13). Quello che hai suggerito per la prima volta, ${STATUS:-0}sembra molto meglio.
Julien Vivenot,

@jvivenot L'uso ${STATUS:-0}fallirà se STATUS=foo, ma ! [ "$STATUS" -eq 200 ] 2> /dev/null && echo foofunziona. IMO, è meglio evitare -eqe usare !=, però.
William Pursell,

28

Prova questo:

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

ha funzionato per me. Penso che potrebbero esserci più di un modo, ma per ora sono soddisfatto.
Kushal Ashok,

27

Prova questo:

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

o

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

plus per l'esempio più pulito
Pawel Cioch,

12

Citazione:

Anche l'operatore "-a" non funziona:

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

Per una spiegazione più elaborata: [e ]non sono parole riservate a Bash. La ifparola chiave introduce un condizionale che deve essere valutato da un lavoro (il condizionale è vero se il valore di ritorno del lavoro è 0o falso altrimenti).

Per test banali, c'è il testprogramma ( man test).

Come alcuni trovano linee come if test -f filename; then foo bar; fi, ecc. Fastidiose, sulla maggior parte dei sistemi trovi un programma chiamato [che in realtà è solo un link simbolico al testprogramma. Quando testviene chiamato come [, devi aggiungere ]come ultimo argomento posizionale.

Quindi if test -f filenameè sostanzialmente lo stesso (in termini di processi generati) di if [ -f filename ]. In entrambi i casi il testprogramma verrà avviato ed entrambi i processi dovrebbero comportarsi in modo identico.

Ecco il tuo errore: if [ $STATUS -ne 200 ] -a [[ "$STRING" != "$VALUE" ]]analizzerà if+ qualche lavoro, il lavoro è tutto tranne lo ifstesso. Il lavoro è solo un semplice comando (Bash parla per qualcosa che si traduce in un singolo processo), il che significa che la prima parola ( [) è il comando e il resto i suoi argomenti posizionali. Ci sono altri argomenti dopo il primo] .

Inoltre no, [[è davvero una parola chiave di Bash, ma in questo caso viene analizzata solo come un normale argomento di comando, perché non è all'inizio del comando.

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.