Un opérateur «et» pour une instruction «if» dans Bash

168

J'essaie de créer un simple script Bash pour vérifier si le site Web est en panne et pour une raison quelconque, l'opérateur "et" ne fonctionne pas:

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

L'opérateur "-a" ne fonctionne pas non plus:

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

Pourriez-vous également indiquer quand utiliser:

  • crochets simples et doubles
  • parenthèse

?

HTF
la source
3
Pourriez-vous être plus précis sur ce qui «ne fonctionne pas»? Avez-vous un message d'erreur spécifique ou ne fournit-il tout simplement pas le résultat attendu?
Julien Vivenot
Je recevais en fait "opérateur unaire attendu", donc il semble que les citations aident
HTF
-aa la duplicité. Lorsqu'il est utilisé avec la testcommande de style Bourne shell , aka [, cela signifie and. Lorsqu'il est utilisé comme expression conditionnelle, il teste pour voir si un fichier existe. Oui, c'est déroutant, mieux vaut éviter.
cdarke

Réponses:

254

Ce que vous avez devrait fonctionner, sauf s'il ${STATUS}est vide. Il vaudrait probablement mieux faire:

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

ou

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

C'est difficile à dire, puisque vous ne nous avez pas montré exactement ce qui ne va pas avec votre script.

Opinion personnelle: ne jamais utiliser [[. Il supprime les messages d'erreur importants et n'est pas portable vers différents shells.

William Pursell
la source
2
Si STATUSest vide, le code de @HTF aurait échoué -ne: unary operator expected. Dans votre cas, cela échouera integer expression expected, n'est-ce pas?
Julien Vivenot
1
Je comprends que. Mais vous mettez en évidence le problème qui $STATUSpourrait être vide et suggérez une solution (en le citant). Votre solution échoue toujours avec un vide STATUS, c'est tout ce que je voulais dire.
Julien Vivenot
1
@jvivenot Vous avez un point. (Ma réponse à votre commentaire a été faite avant que vous ne modifiiez votre commentaire, lorsque votre commentaire se contentait de lire "le code ... aurait échoué". Une solution simple est d'utiliser ${STATUS:-0". Éditera.
William Pursell
Désolé, votre modification ne fonctionne toujours pas. Par exemple: STATUS=; [ $STATUS -ne 13 ] 2>/dev/null && echo foone produit pas de sortie foo, même s'il le devrait (vide est différent de 13). Ce que vous avez suggéré en premier ${STATUS:-0}est bien meilleur.
Julien Vivenot
@jvivenot L'utilisation ${STATUS:-0}échouera si STATUS=foo, mais ! [ "$STATUS" -eq 200 ] 2> /dev/null && echo foofonctionne. OMI, il vaut mieux éviter -eqet utiliser !=, cependant.
William Pursell
28

Essaye ça:

if [ $STATUS -ne 200 -a "$STRING" != "$VALUE" ]; then
BrenanK
la source
travaillé pour moi. Je pense qu'il y a peut-être plus d'une façon mais j'en suis satisfait pour le moment.
Kushal Ashok
27

Essaye ça:

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

ou

if [ ${STATUS} -ne 100 ] && [ "${STRING}" = "${VALUE}" ]
AnshBikram
la source
plus pour l'exemple le plus propre
Pawel Cioch
12

Citation:

L'opérateur "-a" ne fonctionne pas non plus:

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

Pour une explication plus élaborée: [et ]ne sont pas des mots réservés à Bash. Le ifmot clé introduit un conditionnel à évaluer par un travail (le conditionnel est vrai si la valeur de retour du travail est 0ou faux dans le cas contraire).

Pour les tests triviaux, il y a le testprogramme ( man test).

Comme certains trouvent des lignes comme if test -f filename; then foo bar; fi, etc. ennuyeuses, sur la plupart des systèmes, vous trouvez un programme appelé [qui n'est en fait qu'un lien symbolique vers le testprogramme. Quand testest appelé comme [, vous devez ajouter ]comme dernier argument positionnel.

Donc, if test -f filenamec'est fondamentalement le même (en termes de processus engendrés) que if [ -f filename ]. Dans les deux cas, le testprogramme démarre et les deux processus doivent se comporter de la même manière.

Voici votre erreur: if [ $STATUS -ne 200 ] -a [[ "$STRING" != "$VALUE" ]]analysera if+ un travail, le travail étant tout sauf iflui - même. Le travail n'est qu'une simple commande (Bash parle pour quelque chose qui aboutit à un seul processus), ce qui signifie que le premier mot ( [) est la commande et le reste ses arguments de position. Il reste des arguments après le premier] .

Ce n'est pas non plus [[un mot clé Bash, mais dans ce cas, il n'est analysé que comme un argument de commande normal, car il n'est pas au début de la commande.

Jo So
la source