Могу ли я заставить cURL завершиться с ошибкой с кодом выхода, отличным от 0, если код состояния HTTP не равен 200?


239

Я всегда предполагал, что когда curl получил ответ HTTP 500, он возвращал код выхода, который означал сбой (! = 0), но, похоже, это не так.

Есть ли способ, как я могу сделать сбой cURL с кодом выхода, отличным от 0, если код состояния HTTP не 200? Я знаю, что могу использовать, -w "%{http_code}"но это помещает его в STDOUT, а не в качестве кода выхода (кроме того, я также заинтересован в захвате вывода, который я не хочу перенаправлять в файл, но на экран).

Ответы:


264

curl --fail делает часть того, что вы хотите:

от man curl:

-f, --fail

(HTTP) Сбой молча (вообще не выводится) при ошибках сервера. В основном это делается для того, чтобы лучше включать скрипты и т. Д., Чтобы лучше справляться с неудачными попытками. В обычных случаях, когда HTTP-серверу не удается доставить документ, он возвращает HTML-документ с указанием так (что часто также описывает причину и многое другое). Этот флаг предотвратит вывод curl и вернет ошибку 22.

Этот метод не является отказоустойчивым, и бывают случаи, когда неуспешные коды ответов проскальзывают, особенно когда задействована аутентификация (коды ответов 401 и 407).

Но он блокирует вывод на экран.


2
Так какие части это делает и не делает?
rogerdpack

5
@rogerdpack tl; dr он возвращает ненулевое значение, когда обнаруживает неправильный ответ, но не позволяет OP захватить ответ
ускорение

3
Это не перехватывает HTTP 301 Переместить постоянно. Керл все еще дал код выхода 0.
Wisbucky

4
@wisbucky 301 - это не ошибка, это код состояния перенаправления. Ошибки представляют собой коды состояния 4xx и 5xx.
М. Джастин

1
@wisbucky, чтобы выйти из ненулевого состояния в кодах ошибок HTTP и правильно обрабатывать HTTP-перенаправления; curl -f -Lсмотрите этот вопрос для получения подробной информации о том, что -Lделает.
Ноа Суссман

81

Если вы просто хотите отобразить содержимое скрученной страницы, вы можете сделать это:

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

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

При этом содержимое страницы записывается в STDERR при записи кода состояния HTTP в STDOUT, поэтому его можно назначить переменной STATUSCODE .


3
Как насчет того, если я хочу вывести ответ на ошибку (не 200) , но вернуть 0код не состояния из сценария?
Джастин

2
@Justin: а как насчет if [ "$statuscode" -ne 200 ]; then exit "$statuscode"; fi?
Готи

4
@ghoti: поддерживаются только 8-битные коды выхода без знака, так что это может немного сбить с толку.
Деннис

3
Ах, верно - и коды будут переноситься в 8 бит, поэтому ошибка 404 становится выходным значением 148, 500 становится 244. Действительно, сбивает с толку! :-)
ghoti

7
В качестве небольшого изменения это захватывает код в переменной при перенаправлении ответа на стандартный вывод, а не на stderr: { code=$(curl ... as above ...); } 2>&1хитрость заключается в { ... } 2>&1том, что позволяет перенаправлять, не вызывая при этом другую оболочку, как это ( ... )было бы.
Тобия

31

Я смог сделать это с помощью комбинации флагов:

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

--silent скрывает прогресс и ошибку.
--show-error показывает сообщение об ошибке, скрытое параметром --silent
--fail возвращает код завершения> 0 при сбое запроса.


5
Это не показывает ответ сервера. Я не OP, но я подозреваю, что он хотел увидеть любое сообщение об ошибке от сервера, которое возвращается в теле. Кроме того, --silent --show-error --failработает так же, как и просто -f/--fail.
отходы

1
На самом деле, --failвозвращает код завершения 22, как задокументировано .
Вопросы

2
@wisbucky 301 - это не ошибка, это код состояния перенаправления. Ошибки представляют собой коды состояния 4xx и 5xx.
М. Джастин

4
Чтобы быть справедливым по отношению к @wisbucky, оригинальный вопрос гласит: «[...] если код состояния HTTP не равен 200» . Никаких упоминаний об «ошибке» нигде раньше.
Кен

2
@ M.Justin В соответствии с man-страницей curl: этот метод не является отказоустойчивым, и бывают случаи, когда неуспешные коды ответа проскальзывают, особенно когда используется аутентификация (коды ответа 401 и 407).
Юфу

0

Да, есть способ сделать это, но он далеко не очевиден, так как включает в себя 3 варианта скручивания:

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

Это гарантирует, что success (0) происходит только тогда, когда curl завершает работу с окончательным 2xxкодом возврата, и это stdoutполучает тело, и что любые ошибки будут отображаться в stderr.

Обратите внимание, что документация curl может вас немного смущать, поскольку в ней упоминается, что --fail может успешно завершиться для некоторых кодов 401. Основано на тестах, которые не соответствуют действительности, по крайней мере, при использовании с --show-error одновременно.

До сих пор я не смог найти ни одного случая, когда curl вернет успех, когда он не был http-success с этими опциями.


1
это по сути тот же ответ, что и Рикардо Соуза?
knocte
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.