Ein "und" -Operator für eine "if" -Anweisung in Bash


181

Ich versuche, ein einfaches Bash-Skript zu erstellen, um zu überprüfen, ob die Website nicht verfügbar ist. Aus irgendeinem Grund funktioniert der Operator "und" nicht:

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

Der Operator "-a" funktioniert auch nicht:

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

Könnten Sie uns bitte auch mitteilen, wann Sie Folgendes verwenden sollten:

  • einfache und doppelte eckige Klammern
  • Klammern

?


3
Könnten Sie bitte genauer sagen, was "nicht funktioniert"? Haben Sie eine bestimmte Fehlermeldung oder liefert sie einfach nicht die erwartete Ausgabe?
Julien Vivenot

Ich habe tatsächlich "Unary Operator Expected" erhalten, also sieht es so aus, als würde das Zitieren helfen
HTF

-ahat Duplizität. Bei Verwendung mit dem testBefehl Bourne Shell Style , auch bekannt als [, bedeutet dies and. Bei Verwendung als bedingter Ausdruck wird geprüft, ob eine Datei vorhanden ist. Ja, es ist verwirrend, am besten vermieden.
Cdarke

Überprüfen Sie dies heraus: theunixshell.blogspot.com/2013/05/…
Vijay

Antworten:


273

Was Sie haben, sollte funktionieren, es ${STATUS}sei denn, es ist leer. Es wäre wahrscheinlich besser zu tun:

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

oder

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

Es ist schwer zu sagen, da Sie uns nicht genau gezeigt haben, was mit Ihrem Skript falsch läuft.

Persönliche Meinung: niemals benutzen [[. Es unterdrückt wichtige Fehlermeldungen und ist nicht auf verschiedene Shells portierbar.


2
Wenn STATUSleer, wäre der Code von @HTF am fehlgeschlagen -ne: unary operator expected. In Ihrem Fall wird es fehlschlagen integer expression expected, nicht wahr?
Julien Vivenot

1
Ich verstehe das. Sie markieren jedoch das $STATUSmöglicherweise leere Problem und schlagen eine Lösung vor (unter Angabe). Ihre Lösung schlägt immer noch mit einem leeren fehl STATUS, das ist alles, was ich gemeint habe.
Julien Vivenot

1
@jvivenot Du hast einen Punkt. (Meine Antwort auf Ihren Kommentar wurde abgegeben, bevor Sie Ihren Kommentar bearbeitet haben, als Ihr Kommentar lediglich "der Code ... wäre fehlgeschlagen" lautete. Eine einfache Lösung ist die Verwendung ${STATUS:-0". Wird bearbeitet.
William Pursell

Entschuldigung, Ihre Bearbeitung funktioniert immer noch nicht. Beispiel: STATUS=; [ $STATUS -ne 13 ] 2>/dev/null && echo fooWird nicht ausgegeben foo, obwohl dies der Fall sein sollte (leer ist anders als 13). Was Sie zuerst vorgeschlagen haben, ${STATUS:-0}sieht viel besser aus.
Julien Vivenot

@jvivenot Die Verwendung schlägt ${STATUS:-0}fehl STATUS=foo, ! [ "$STATUS" -eq 200 ] 2> /dev/null && echo foofunktioniert aber . IMO ist es jedoch besser zu vermeiden -eqund zu verwenden !=.
William Pursell

37

Versuche dies:

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

oder

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

1
Plus für sauberstes Beispiel
Pawel Cioch

29

Versuche dies:

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

arbeitete für mich. Ich denke, es gibt mehr als einen Weg, aber ich bin damit vorerst zufrieden.
Kushal Ashok

13

Zitat:

Der Operator "-a" funktioniert auch nicht:

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

Für eine ausführlichere Erklärung: [und ]sind keine Bash reservierten Wörter. Das ifSchlüsselwort führt eine Bedingung ein, die von einem Job ausgewertet werden soll (die Bedingung ist wahr, wenn der Rückgabewert des Jobs ist0 oder anderweitig falsch).

Für triviale Tests gibt es das testProgramm (man test ).

Wie manche Zeilen if test -f filename; then foo bar; fiusw. als störend empfinden, finden Sie auf den meisten Systemen ein Programm namens, [das eigentlich nur ein Symlink zum testProgramm ist. Wenn testals aufgerufen wird [, müssen Sie ]als letztes Positionsargument hinzufügen .

So if test -f filenameist im Grunde das gleiche (in Bezug auf Prozesse erzeugt) wie if [ -f filename ]. In beiden Fällen ist dietest Programm gestartet und beide Prozesse sollten sich identisch verhalten.

Hier ist Ihr Fehler: if [ $STATUS -ne 200 ] -a [[ "$STRING" != "$VALUE" ]]Wird zu if+ einem Job analysiert , wobei der Job alles außer dem ifselbst ist. Der Job ist nur ein einfacher Befehl (Bash spricht für etwas, das zu einem einzigen Prozess führt), was bedeutet, dass das erste Wort ( [) der Befehl und der Rest seine Positionsargumente ist. Nach dem ersten sind noch Argumente übrig] .

Auch nicht, [[ist in der Tat ein Bash-Schlüsselwort, aber in diesem Fall wird es nur als normales Befehlsargument analysiert, da es nicht am Anfang des Befehls steht.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.