Czy mogę spowodować niepowodzenie cURL z kodem wyjścia innym niż 0, jeśli kod stanu HTTP nie ma wartości 200?

238

Zawsze zakładałem, że kiedy curl otrzymał odpowiedź HTTP 500, zwracał kod wyjścia, który oznaczał błąd (! = 0), ale wydaje się, że tak nie jest.

Czy istnieje sposób, w jaki mogę sprawić, że cURL nie powiedzie się z kodem wyjścia innym niż 0, jeśli kod stanu HTTP nie ma wartości 200? Wiem, że mogę użyć, -w "%{http_code}"ale to umieszcza go w STDOUT, nie jako kod wyjścia (poza tym, jestem również zainteresowany przechwytywaniem danych wyjściowych, których nie chcę przekierowywać do pliku, ale na ekran).

knocte
źródło

Odpowiedzi:

262

curl --fail robi część tego, co chcesz:

z man curl:

-f, --fail

(HTTP) Błąd cicho (brak danych wyjściowych) w przypadku błędów serwera. Odbywa się to głównie w celu lepszego włączenia skryptów itp. W celu lepszego radzenia sobie z nieudanymi próbami. W normalnych przypadkach, gdy serwer HTTP nie dostarcza dokumentu, zwraca dokument HTML stwierdzający, że tak (co często opisuje również dlaczego i więcej). Ta flaga zapobiegnie wysyłaniu tego przez curl i zwróci błąd 22.

Ta metoda nie jest bezpieczna w razie awarii i zdarzają się sytuacje, w których kody nieudanej odpowiedzi prześlizgną się, szczególnie w przypadku uwierzytelnienia (kody odpowiedzi 401 i 407).

Ale blokuje wyjście na ekran.

szaleństwo
źródło
2
Więc które części to robi, a czego nie?
rogerdpack 18.07.16
5
@rogerdpack tl; dr zwraca wartość niezerową, gdy wykryje złą odpowiedź, ale nie pozwoli OP przechwycić odpowiedzi
rampion
3
Nie przechwytuje to HTTP 301 Move Permanently. curl nadal dał kod wyjścia 0.
wisbucky
4
@wisbucky 301 nie jest błędem, to kod statusu przekierowania. Błędy to kody stanu 4xx i 5xx.
M. Justin,
1
@wisbucky, aby wyjść z niezerowych kodów błędów HTTP i poprawnie obsługiwać przekierowania HTTP curl -f -Li zobacz to pytanie, aby uzyskać szczegółowe informacje na temat tego, co -Ldziała
Noah Sussman
81

Jeśli chcesz tylko wyświetlić zawartość zwiniętej strony, możesz to zrobić:

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

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

Spowoduje to zapisanie zawartości strony do STDERR podczas pisania kodu stanu HTTP do STDOUT, dzięki czemu można go przypisać do zmiennej STATUSCODE .

Dennis
źródło
3
Co powiesz na to, że jeśli chcę wypisać odpowiedź w przypadku niepowodzenia (nie 200) , ale zwrócę 0ze skryptu kod inny niż status?
Justin
2
@Justin: A co z if [ "$statuscode" -ne 200 ]; then exit "$statuscode"; fi?
ghoti
4
@ghoti: Obsługiwane są tylko 8-bitowe kody wyjścia bez znaku, więc może to być nieco mylące.
Dennis
3
Ach, prawda - i kody będą zawijać się na 8 bitach, więc błąd 404 staje się wartością wyjściową 148, 500 zmienia się na 244. Rzeczywiście, mylące! :-)
ghoti
7
Jako niewielką odmianę, przechwytuje kod w zmiennej podczas przekierowywania odpowiedzi na stdout, a nie stderr: { code=$(curl ... as above ...); } 2>&1sztuczka polega na { ... } 2>&1tym, że pozwala na przekierowanie, ale nie powoduje odrodzenia innej powłoki, jak ( ... )by to było.
Tobia
31

Byłem w stanie to zrobić za pomocą kombinacji flag:

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

--silent ukrywa postęp i błąd
--show-error pokazuje komunikat o błędzie ukryty przez --silent
--fail zwraca kod wyjścia> 0, gdy żądanie nie powiedzie się

Ricardo Souza
źródło
5
To nie pokazuje odpowiedzi serwera. Nie jestem OP, ale podejrzewam, że chciał zobaczyć komunikat o błędzie z serwera zwrócony w treści. Poza tym --silent --show-error --faildziała tak samo jak tylko -f/--fail.
marnuj
1
W rzeczywistości --failzwraca kod wyjścia 22, jak udokumentowano .
Pytania do kolonistów,
2
@wisbucky 301 nie jest błędem, to kod statusu przekierowania. Błędy to kody stanu 4xx i 5xx.
M. Justin,
4
Aby być sprawiedliwym wobec @wisbucky, oryginalne pytanie brzmi „[...] jeśli kod stanu HTTP nie ma wartości 200” . Nigdy wcześniej nie wspominano o „błędzie”.
Ken
2
@ M.Justin Według curl man-page: Ta metoda nie jest bezpieczna w razie awarii i zdarzają się przypadki, gdy kody nieudanych odpowiedzi prześlizgną się, szczególnie gdy dotyczy uwierzytelnienia (kody odpowiedzi 401 i 407).
youfu
0

Tak, jest na to sposób, ale nie jest to oczywiste, ponieważ obejmuje 3 opcje zwijania:

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

To gwarantuje, że sukces (0) nastąpi tylko wtedy, gdy zwiniesz nas końcowym 2xxkodem powrotu i stdoutotrzymamy treść, a wszelkie błędy zostaną wyświetlone stderr.

Należy pamiętać, że dokumentacja curl może nieco cię pomylić, ponieważ wspomina, że ​​--fail może się powieść dla około 401 kodów. Na podstawie testów, które nie są prawdziwe, a przynajmniej nie w przypadku jednoczesnego użycia z --show-error.

Do tej pory nie byłem w stanie znaleźć żadnego przypadku, w którym curl zwróci sukces, gdy nie byłoby HTTP z tymi opcjami.

sorin
źródło
1
czy jest to w zasadzie ta sama odpowiedź, co odpowiedź Ricarda Souzy?
knocte