¿Puedo hacer que cURL falle con un código de salida diferente de 0 si el código de estado HTTP no es 200?

239

Siempre estaba asumiendo que cuando rizo consiguió una respuesta HTTP 500 se devuelve un código de salida que significó el fracaso (! = 0), pero que parece ser no el caso.

¿Hay alguna manera de hacer que cURL falle con un código de salida diferente de 0 si el código de estado HTTP no es 200? Sé que puedo usar, -w "%{http_code}"pero eso lo pone en STDOUT, no como el código de salida (además, también estoy interesado en capturar la salida, que no quiero redirigir a un archivo, sino a la pantalla).

knocte
fuente

Respuestas:

264

curl --fail hace parte de lo que quieres:

de man curl:

-f, --fail

(HTTP) Falla silenciosa (sin salida en absoluto) en los errores del servidor. Esto se hace principalmente para habilitar mejor los scripts, etc., para tratar mejor los intentos fallidos. En casos normales, cuando un servidor HTTP no puede entregar un documento, devuelve un documento HTML que lo indica (que a menudo también describe por qué y más). Esta bandera evitará que curl salga y devolverá el error 22.

Este método no es a prueba de fallas y hay ocasiones en las que los códigos de respuesta no exitosos se deslizarán, especialmente cuando se trata de autenticación (códigos de respuesta 401 y 407).

Pero bloquea la salida a la pantalla.

rampion
fuente
2
Entonces, ¿qué partes hace y no hace?
rogerdpack
55
@rogerdpack tl; dr no devuelve cero cuando detecta una mala respuesta, pero no deja que OP capture la respuesta
rampion
3
Esto no atrapa HTTP 301 Move permanentemente. curl todavía dio el código de salida 0.
wisbucky
44
@wisbucky 301 no es un error, es un código de estado de redirección. Los errores son códigos de estado 4xx y 5xx.
M. Justin
1
@wisbucky para salir de cero en los códigos de error HTTP y manejar correctamente las redirecciones HTTP, curl -f -Lconsulte esta pregunta para obtener detalles sobre qué -Lhace.
Noah Sussman
81

Si solo desea mostrar el contenido de la página curvada, puede hacer esto:

STATUSCODE=$(curl --silent --output /dev/stderr --write-out "%{http_code}" URL)

if test $STATUSCODE -ne 200; then
    # error handling
fi

Esto escribe el contenido de la página en STDERR mientras escribe el código de estado HTTP en STDOUT, por lo que puede asignarse a la variable STATUSCODE .

Dennis
fuente
3
¿Qué tal si quiero generar la respuesta en caso de falla (no 200) , pero devuelvo un 0código de no estado del script?
Justin
2
@Justin: ¿Qué pasa if [ "$statuscode" -ne 200 ]; then exit "$statuscode"; fi?
ghoti
44
@ghoti: solo se admiten códigos de salida de 8 bits sin firmar, por lo que podría ser un poco confuso.
Dennis
3
Ah, correcto, y los códigos se ajustarán a 8 bits, por lo que el error 404 se convierte en el valor de salida 148, 500 se convierte en 244. ¡Confuso en verdad! :-)
ghoti
77
Como una ligera variación, esto captura el código en una variable mientras redirige la respuesta a stdout, no stderr: { code=$(curl ... as above ...); } 2>&1el truco es { ... } 2>&1que permite redirigir, sin generar un shell diferente como lo ( ... )haría.
Tobia
31

Pude hacerlo usando una combinación de banderas:

curl --silent --show-error --fail URL

--silent oculta el progreso y el error
--show-error muestra el mensaje de error oculto por --silent
--fail devuelve un código de salida> 0 cuando falla la solicitud

Ricardo Souza
fuente
55
Esto no muestra la respuesta del servidor. No soy OP pero sospecho que quería ver algún mensaje de error del servidor que se devuelve en el cuerpo. Además un --silent --show-error --failfunciona igual que solo -f/--fail.
desperdicio
1
En realidad, --faildevuelve el código de salida 22, como se documenta .
Preguntas de Quolonel
2
@wisbucky 301 no es un error, es un código de estado de redirección. Los errores son códigos de estado 4xx y 5xx.
M. Justin
44
Para ser justos con @wisbucky, la pregunta original dice "[...] si el código de estado HTTP no es 200" . No se menciona el "error" en ninguna parte anterior.
Ken
2
@ M.Justin Según la página de manual curl: Este método no es a prueba de fallas y hay ocasiones en las que los códigos de respuesta no exitosos se deslizarán, especialmente cuando se trata de autenticación (códigos de respuesta 401 y 407).
youfu
0

Sí, hay una manera de hacerlo, pero está lejos de ser obvio, ya que involucra 3 opciones de rizo:

curl -s --fail --show-error https://httpbin.org/status/200 > /dev/null
curl -s --fail --show-error https://httpbin.org/status/401 > /dev/null
curl -s --fail --show-error https://httpbin.org/status/404 > /dev/null
curl -s --fail --show-error https://bleah-some-wrong-host > /dev/null

Esto asegura que el éxito (0) ocurre solo cuando curl end-us con el 2xxcódigo de retorno final y eso stdoutobtiene el cuerpo y que cualquier error se mostrará a stderr.

Tenga en cuenta que la documentación de curl puede confundirlo un poco porque menciona que --fail podría tener éxito para algunos códigos 401. Basado en pruebas que no son ciertas, al menos no cuando se usa con --show-error al mismo tiempo.

Hasta ahora no pude encontrar ningún caso en el que curl devuelva el éxito cuando no fue un éxito http con estas opciones.

Sorin
fuente
1
¿Es esta esencialmente la misma respuesta que la de Ricardo Souza?
Knocte