2010-02-08 15 views
123

Tengo la sensación de que me falta lo obvio, pero no lo he logrado con man [curl|wget] o google ("http" hace un término de búsqueda tan malo). Estoy buscando una solución sucia & rápida a uno de nuestros servidores web que falla con frecuencia, devolviendo el código de estado 500 con un mensaje de error. Una vez que esto sucede, debe reiniciarse.¿Cómo evaluar los códigos de respuesta http del script bash/shell?

Como la causa principal parece ser difícil de encontrar, estamos buscando una solución rápida, con la esperanza de que sea suficiente para cerrar el tiempo hasta que podamos arreglarlo (el servicio no necesita alta disponibilidad)

La solución propuesta es crear un trabajo cron que se ejecute cada 5 minutos, verificando http://localhost:8080/. Si esto vuelve con el código de estado 500, el servidor web se reiniciará. El servidor se reiniciará en menos de un minuto, por lo que no es necesario verificar si los reinicios ya se están ejecutando.

El servidor en cuestión es una instalación mínima de ubuntu 8.04 con suficientes paquetes instalados para ejecutar lo que necesita actualmente. No es un requisito difícil realizar la tarea en bash, pero me gustaría que se ejecutara en un entorno tan mínimo sin instalar más intérpretes.

(estoy lo suficientemente familiarizado con secuencias de comandos que el comando/opciones para asignar el código de estado HTTP para una variable de entorno sería suficiente - esto es lo que he buscado y no podía encontrar.)

Respuesta

208

I no han probado esto en un código 500, pero funciona en otros como 200, 302 y 404.

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

Agradable, gracias: ya he encontrado -write-out, pero he perdido el --output/dev/null. Cuando todo el contenido viene con él, el código de respuesta se pierde en demasiada información, así que simplemente no lo vi ... –

+3

¿Puedo almacenar tanto el código de respuesta como el resultado en variables separadas? Me gustaría hacer eco de la salida cuando el código de respuesta no es 200 –

+5

@VaibhavBajpai: Pruebe esto: 'response = $ (curl --write-out \\ n% {http_code} --silent --output - servername)' - la última línea en el resultado será el código de respuesta. –

8

Con netcat y awk que puede manejar la respuesta del servidor manualmente:

if netcat 127.0.0.1 8080 <<EOF | awk 'NR==1{if ($2 == "500") exit 0; exit 1;}'; then 
GET/HTTP/1.1 
Host: www.example.com 

EOF 

    apache2ctl restart; 
fi 
+1

Agradable - muchas gracias –

+3

Esto es material hardcore – alonisser

13

aquí:

url='http://localhost:8080/' 
status=$(r=(IFS=' ';$(curl -Is --connect-timeout 5 "${url}" || echo 1 500));echo ${r[1]}) 
[ status -eq 500 ] && bounce # assuming the bounce script is called 'bounce' 

O ponerlo todo en una línea:

[ 500 -eq $(r=(IFS=' ';$(curl -Is --connect-timeout 5 'http://localhost:8080/' || echo 1 500));echo ${r[1]}) ] && bounce 

de explicar, la respuesta HTTP contiene siempre el estado del servidor como parte de la primera línea de la respuesta, como:

HTTP/1.1 200 OK 
HTTP/1.0 404 NOT FOUND 

La secuencia de comandos simplemente utiliza curl para hacer una solicitud HEAD a localhost: 8080. Convierte el encabezado HTTP en una matriz y devuelve el segundo elemento. Para simplificar el manejo de fallas, si el HEAD no se conecta dentro de los 5 segundos o el rizo falla por alguna razón, también se devuelve 500.

+0

Muchas gracias. –

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

funciona. De lo contrario, debe presionar regresar para ver el código en sí.

7

Para seguir 3XX redirige y códigos de respuesta para todas las solicitudes de impresión:

HTTP_STATUS="$(curl -IL --silent example.com | grep HTTP)";  
echo "${HTTP_STATUS}"; 
+0

El 'grep' capturará todas las líneas con" HTTP "en ellas. Tal vez 'grep -m 1 HTTP' solo capte la primera coincidencia, si esa es la intención, o tal vez canalizar a Awk para analizar solo el código de resultado. – tripleee

1

esto puede ayudar a evaluar el estado de http

var=`curl -I http://www.example.org 2>/dev/null | head -n 1 | awk -F" " '{print $2}'` 
echo http:$var 
+1

'head -n 1 | awk '{stuff}' 'es un poco antipattern,' awk 'NR == 1 {stuff}' 'hace lo mismo en un proceso, Awk puro. – tripleee

0

Para añadir a @DennisWilliamson comentario anterior:

@VaibhavBajpai: Pruebe esto: response = $ (curl --write-out \ n% {http_code} --silent --output - servername) - la última línea en la res ULT será el código de respuesta

A continuación, puede analizar el código de respuesta de la respuesta de usar algo como lo siguiente, donde X puede significar una expresión regular para marcar el final de la respuesta (utilizando un ejemplo JSON aquí)

X='*\}' 
code=$(echo ${response##$X}) 

Ver subcadena Remoción: http://tldp.org/LDP/abs/html/string-manipulation.html

+0

¿Por qué pondría el patrón en una variable y por qué usaría un [echo inútil'] (http://www.iki.fi/era/unix/award.html # echo) para obtener el valor final? Simplemente 'code = $ {response ## * \}}' es más simple y evita una serie de riesgos comunes. Además, ese es un patrón glob, no una expresión regular adecuada. – tripleee

1

Otra variación:

status=$(curl -I https://www.healthdata.gov/user/login 2> /dev/null | head -n 1 | cut -d ' ' -f 2) 
1

Aquí viene el guion largo, pero fácil de entender, inspirado en la solución nicerobot, que solo solicita los encabezados de respuesta y evita el uso de IFS como se sugiere here. Emite un mensaje de rebote cuando encuentra una respuesta> = 400. Este eco se puede reemplazar con un bounce-script.

# set the url to probe 
url='http://localhost:8080' 
# use curl to request headers (return sensitive default on timeout: "timeout 500"). Parse the result into an array (avoid settings IFS, instead use read) 
read -ra result <<< $(curl -Is --connect-timeout 5 "${url}" || echo "timeout 500") 
# status code is second element of array "result" 
status=${result[1]} 
# if status code is greater than or equal to 400, then output a bounce message (replace this with any bounce script you like) 
[ $status -ge 400 ] && echo "bounce at $url with status $status" 
1

Necesitaba demo algo rápidamente hoy y se me ocurrió esto. Pensé que lo ubicaría aquí si alguien necesitaba algo similar a la solicitud del 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" "[email protected]" -r "STATUS_CHECKER" 
else 
    exit 0 
fi 

Esto enviará una alerta por correo electrónico en cada cambio de estado de 200, por lo que es tonto y potencialmente codicioso. Para mejorar esto, consideraría recorrer varios códigos de estado y realizar diferentes acciones dependiendo del resultado.

Cuestiones relacionadas