Posso fazer com que cURL falhe com um exitCode diferente de 0 se o código de status HTTP não for 200?

239

Eu estava sempre assumindo que, quando o curl recebia uma resposta HTTP 500, estava retornando um código de saída que significava falha (! = 0), mas esse parece não ser o caso.

Existe uma maneira de fazer com que o cURL falhe com um exitCode diferente de 0 se o código de status HTTP não for 200? Eu sei que posso usar, -w "%{http_code}"mas isso o coloca em STDOUT, não como o código de saída (além disso, também estou interessado em capturar a saída, que não quero redirecionar para um arquivo, mas para a tela).

knocte
fonte

Respostas:

264

curl --fail faz parte do que você deseja:

de man curl:

-f, --fail

(HTTP) falha silenciosamente (sem saída) nos erros do servidor. Isso é feito principalmente para melhor habilitar scripts, etc., para lidar melhor com tentativas falhas. Em casos normais, quando um servidor HTTP falha na entrega de um documento, ele retorna um documento HTML informando isso (que geralmente também descreve o porquê e mais). Este sinalizador impedirá que a ondulação produza isso e retorne o erro 22.

Esse método não é à prova de falhas e há ocasiões em que os códigos de resposta sem êxito passarão, especialmente quando a autenticação estiver envolvida (códigos de resposta 401 e 407).

Mas ele bloqueia a saída na tela.

rampion
fonte
2
Então, quais partes ele faz e não faz?
Rogerdpack
5
@rogerdpack tl; dr ele retornar diferente de zero quando detecta uma resposta ruim, mas não deixaria de captura de OP a resposta
rampion
3
Isso não captura o HTTP 301 Move Permanently. o curl ainda deu o código de saída 0. #
wisbucky 11/1118
4
@wisbucky 301 não é um erro, é um código de status de redirecionamento. Os erros são códigos de status 4xx e 5xx.
8188 Justin M.
1
@wisbucky para sair diferente de zero em códigos de erro HTTP e manipular redirecionamentos HTTP, use corretamente curl -f -Le consulte esta pergunta para obter detalhes sobre o que -Lfaz.
Noah Sussman
81

Se você quiser apenas exibir o conteúdo da página ondulada, faça o seguinte:

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

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

Isso grava o conteúdo da página em STDERR enquanto grava o código de status HTTP em STDOUT, para que possa ser atribuído à variável STATUSCODE .

Dennis
fonte
3
Que tal se eu quiser gerar a resposta em caso de falha (não 200) , mas retornar um 0código não de status do script?
236 Justin Justin
2
@ Justin: Que tal if [ "$statuscode" -ne 200 ]; then exit "$statuscode"; fi?
ghoti
4
@hothot: Apenas códigos de saída não assinados de 8 bits são suportados, o que pode tornar um pouco confuso.
Dennis
3
Ah, certo - e os códigos serão quebrados em 8 bits, então o erro 404 se torna o valor de saída 148, 500 se torna 244. De fato, confuso! :-)
ghoti 17/06/2015
7
Como uma pequena variação, isso captura o código em uma variável enquanto redireciona a resposta para stdout, não stderr: { code=$(curl ... as above ...); } 2>&1O truque é { ... } 2>&1que permite redirecionar, sem gerar um shell diferente como ( ... )faria.
Tobia 23/05
31

Consegui fazer isso usando uma combinação de sinalizadores:

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

--silent oculta o progresso e o erro
--show-error mostra a mensagem de erro oculta por --silent
--fail retorna um código de saída> 0 quando a solicitação falha

Ricardo Souza
fonte
5
Isso não mostra a resposta do servidor. Não sou OP, mas suspeito que ele queria ver qualquer mensagem de erro do servidor que é retornada no corpo. Além de um --silent --show-error --failfunciona o mesmo que apenas -f/--fail.
waste
1
Na verdade, --failretorna o código de saída 22, conforme documentado .
Quolonel Perguntas
2
@wisbucky 301 não é um erro, é um código de status de redirecionamento. Os erros são códigos de status 4xx e 5xx.
8188 Justin M.
4
Para ser justo com @wisbucky, a pergunta original indica "[...] se o código de status HTTP não for 200" . Nenhuma menção de "erro" em qualquer lugar anterior.
ken
2
@ M.Justin De acordo com a página de manual curl: Este método não é à prova de falhas e há ocasiões em que códigos de resposta sem êxito serão detectados, especialmente quando houver autenticação (códigos de resposta 401 e 407).
youfu
0

Sim, existe uma maneira de fazer isso, mas está longe de ser óbvio, pois envolve três opções de ondulação:

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

Isso garante que o sucesso (0) ocorra somente quando o enrolamento finalizar com o 2xxcódigo de retorno final e que stdoutobtém o corpo e que quaisquer erros sejam exibidos no stderr.

Observe que a documentação do curl pode confundir um pouco você, pois menciona que --fail pode ter êxito em alguns códigos 401. Com base em testes que não são verdadeiros, pelo menos não quando usados ​​com --show-error ao mesmo tempo.

Até o momento, não consegui encontrar nenhum caso em que o curl retornasse êxito quando não havia um http com êxito com essas opções.

sorin
fonte
1
essa é essencialmente a mesma resposta que a de Ricardo Souza?
knocte 4/09