249 votes

Comment évaluer les codes de réponse http à partir de bash/shell script ?

J'ai l'impression de passer à côté de l'évidence, mais je n'ai pas réussi à man [curl|wget] ou Google (le terme "http" n'est pas un bon critère de recherche). Je suis à la recherche d'une solution rapide pour l'un de nos serveurs Web qui échoue fréquemment, renvoyant le code d'état 500 avec un message d'erreur. Une fois que cela se produit, il doit être redémarré.

Comme la cause fondamentale semble difficile à trouver, nous cherchons une solution rapide, en espérant qu'elle suffira à combler le temps jusqu'à ce que nous puissions vraiment la réparer (le service n'a pas besoin de haute disponibilité).

La solution proposée est de créer une tâche cron qui s'exécute toutes les 5 minutes, vérifiant http://localhost:8080/ . Si le code d'état 500 est renvoyé, le serveur Web sera redémarré. Le serveur sera redémarré en moins d'une minute, il n'est donc pas nécessaire de vérifier si des redémarrages sont déjà en cours.

Le serveur en question est une installation minimale ubuntu 8.04 avec juste assez de paquets installés pour faire fonctionner ce dont il a besoin actuellement. Il n'y a pas d'exigence stricte pour effectuer la tâche en bash, mais j'aimerais qu'elle fonctionne dans un tel environnement minimal sans installer d'autres interpréteurs.

(Je suis suffisamment familier avec les scripts pour que la commande/les options permettant d'assigner le code d'état http à une variable d'environnement soient suffisantes - c'est ce que j'ai cherché et que je n'ai pas trouvé).

377voto

Dennis Williamson Points 105818

Je n'ai pas testé cela sur un code 500, mais cela fonctionne sur d'autres comme 200, 302 et 404.

response=$(curl --write-out '%{http_code}' --silent --output /dev/null servername)

Note, le format fourni pour --write-out doit être cité. Comme suggéré par @ibai, ajoutez --head pour faire une demande HEAD uniquement. Cela permet de gagner du temps lorsque la récupération est réussie puisque le contenu de la page ne sera pas transmis.

1 votes

Bien - merci : J'ai déjà trouvé --write-out, mais j'ai manqué le --output /dev/null. Quand tout le contenu vient avec, le code de réponse se perd dans trop d'informations, donc je ne l'ai tout simplement pas vu...

6 votes

Puis-je stocker le code de réponse et la sortie dans des variables distinctes ? J'aimerais que le résultat soit affiché lorsque le code de réponse n'est pas 200.

8 votes

@VaibhavBajpai : Essaie ça : response=$(curl --write-out \\n%{http_code} --silent --output - servername) - la dernière ligne du résultat sera le code de réponse.

58voto

Chris Gillatt Points 131

J'avais besoin de faire une démonstration rapide aujourd'hui et j'ai trouvé ça. J'ai pensé le placer ici si quelqu'un avait besoin de quelque chose de similaire à la demande de l'OP.

#!/bin/bash

status_code=$(curl --write-out %{http_code} --silent --output /dev/null www.bbc.co.uk/news)

if [[ "$status_code" -ne 200 ]] ; then
  echo "Site status changed to $status_code" | mail -s "SITE STATUS CHECKER" "my_email@email.com" -r "STATUS_CHECKER"
else
  exit 0
fi

Cela enverra une alerte par courriel à chaque changement d'état à partir de 200, c'est donc stupide et potentiellement gourmand. Pour améliorer cela, je chercherais à boucler sur plusieurs codes d'état et à effectuer différentes actions en fonction du résultat.

52voto

hd1 Points 11522
curl --write-out "%{http_code}\n" --silent --output /dev/null "$URL"

fonctionne. Si ce n'est pas le cas, vous devez appuyer sur retour pour afficher le code lui-même.

28voto

nicerobot Points 4811

Bien que le réponse acceptée est une bonne réponse, elle néglige les scénarios d'échec. curl retournera 000 s'il y a une erreur dans la demande ou un échec de la connexion.

url='http://localhost:8080/'
status=$(curl --head --location --connect-timeout 5 --write-out %{http_code} --silent --output /dev/null ${url})
[[ $status == 500 ]] || [[ $status == 000 ]] && echo restarting ${url} # do start/restart logic

Note : cela va un peu au-delà de ce qui est demandé 500 pour confirmer également que curl peut même se connecter au serveur (c'est-à-dire que les retours 000 ).

Créez une fonction à partir de celle-ci :

failureCode() {
    local url=${1:-http://localhost:8080}
    local code=${2:-500}
    local status=$(curl --head --location --connect-timeout 5 --write-out %{http_code} --silent --output /dev/null ${url})
    [[ $status == ${code} ]] || [[ $status == 000 ]]
}

Test pour obtenir un 500 :

failureCode http://httpbin.org/status/500 && echo need to restart

Erreur de réception du test/échec de la connexion (c.-à-d. 000 ) :

failureCode http://localhost:77777 && echo need to start

Test n'obtenant pas de 500 :

failureCode http://httpbin.org/status/400 || echo not a failure

11voto

AG6HQ Points 324

Voici mon implémentation, qui est un peu plus verbeuse que certaines des réponses précédentes

curl https://somewhere.com/somepath   \
--silent \
--insecure \
--request POST \
--header "your-curl-may-want-a-header" \
--data @my.input.file \
--output site.output \
--write-out %{http_code} \
  > http.response.code 2> error.messages
errorLevel=$?
httpResponse=$(cat http.response.code)

jq --raw-output 'keys | @csv' site.output | sed 's/"//g' > return.keys
hasErrors=`grep --quiet --invert errors return.keys;echo $?`

if [[ $errorLevel -gt 0 ]] || [[ $hasErrors -gt 0 ]] || [[ "$httpResponse" != "200" ]]; then
  echo -e "Error POSTing https://somewhere.com/somepath with input my.input (errorLevel $errorLevel, http response code $httpResponse)" >> error.messages
  send_exit_message # external function to send error.messages to whoever.
fi

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X