Script per ottenere il codice di stato HTTP di un elenco di URL?


87

Ho un elenco di URL che devo controllare, per vedere se funzionano ancora o meno. Vorrei scrivere uno script bash che lo faccia per me.

Ho solo bisogno del codice di stato HTTP restituito, cioè 200, 404, 500 e così via. Niente di più.

MODIFICA Nota che c'è un problema se la pagina dice "404 non trovato" ma restituisce un messaggio di 200 OK. È un server Web configurato in modo errato, ma potrebbe essere necessario considerare questo caso.

Per ulteriori informazioni, vedi Controllare se un URL va a una pagina contenente il testo "404"


2
Per essere onesti, il "bug" del mio script è solo quando il server restituisce il codice HTTP 200 ma il testo del corpo dice "404 non trovato", che è un server web che si comporta male.
Phil il

2
Lo stato di uscita di wget sarà 0 se il codice di risposta era 200, 8 se 404, 4 se 302 ... Puoi usare $? variabile per accedere allo stato di uscita del comando precedente.
Casey Watson

Risposte:


194

Curl ha un'opzione specifica --write-out, per questo:

$ curl -o /dev/null --silent --head --write-out '%{http_code}\n' <url>
200
  • -o /dev/null butta via il solito output
  • --silent getta via il misuratore di avanzamento
  • --head effettua una richiesta HTTP HEAD, invece di GET
  • --write-out '%{http_code}\n' stampa il codice di stato richiesto

Per concludere questo in uno script Bash completo:

#!/bin/bash
while read LINE; do
  curl -o /dev/null --silent --head --write-out "%{http_code} $LINE\n" "$LINE"
done < url-list.txt

(I lettori con gli occhi d'aquila noteranno che questo utilizza un processo di curl per URL, che impone penalità per la connessione fork e TCP. Sarebbe più veloce se più URL fossero combinati in un singolo curl, ma non c'è spazio per scrivere la mostruosa ripetizione di opzioni che il curl richiede per farlo.)


Molto bella. Posso eseguire quel comando su ogni URL nel mio file?
Manu

1
@Manu: Sì, ho modificato la mia risposta per mostrare un possibile modo di concludere il comando curl. Si presuppone che url-list.txt contenga un URL per riga.
Phil

1
Non so perché lo script dall'alto e la risposta mi ottengono sempre 000 nell'output, ma quando eseguo il comando solo una volta senza loop funziona ...
Karol F

1
@KarolFiturski Ho avuto lo stesso problema (che probabilmente hai risolto da allora, ma nel caso in cui qualcun altro si imbattesse in questo ...) nel mio caso ho avuto ritorni a capo alle estremità della riga del mio file di input, facendo sì che gli URL siano come http://example.com/\rdurante il giro
Jordan Robinson,

1
Ho avuto questo problema e sono stato in grado di risolverlo cambiando la riga che termina dal tipo Windows al tipo Linux.
Tristan

38
wget --spider -S "http://url/to/be/checked" 2>&1 | grep "HTTP/" | awk '{print $2}'

stampa solo il codice di stato per te


9
+1 Mostra più codici quando un URL viene reindirizzato, ciascuno su una nuova riga.
Ashfame

Ho dovuto sbarazzarmi del --spider perché funzionasse con la richiesta che stavo cercando di fare, ma funziona.
amitavk

30

Estendendo la risposta già fornita da Phil. Aggiungere il parallelismo è un gioco da ragazzi in bash se usi xargs per la chiamata.

Qui il codice:

xargs -n1 -P 10 curl -o /dev/null --silent --head --write-out '%{url_effective}: %{http_code}\n' < url.lst

-n1 : usa solo un valore (dalla lista) come argomento per la chiamata curl

-P10 : Mantieni attivi 10 processi di curl in qualsiasi momento (ovvero 10 connessioni parallele)

Controlla il write_outparametro nel manuale di curl per più dati che puoi estrarre usandolo (tempi, ecc.).

Nel caso in cui aiuti qualcuno, questa è la chiamata che sto utilizzando attualmente:

xargs -n1 -P 10 curl -o /dev/null --silent --head --write-out '%{url_effective};%{http_code};%{time_total};%{time_namelookup};%{time_connect};%{size_download};%{speed_download}\n' < url.lst | tee results.csv

Produce solo un mucchio di dati in un file CSV che può essere importato in qualsiasi strumento di Office.


2
Parallelismo, input di file e csv. Esattamente quello che stavo cercando.
Agey

Brillante, ha reso la mia giornata.
xlttj

Questo è fantastico, proprio quello che stavo cercando, grazie signore. Una domanda, come si potrebbe includere il titolo della pagina della pagina nei risultati CSV?
MitchellK

@estani - stackoverflow.com/users/1182464/estani come si potrebbe includere ottenere il titolo della pagina di una pagina nel file .csv. Ci scusiamo per il repost, ho dimenticato di taggarti in modo da ricevere una notifica su questa domanda. Grazie molto.
MitchellK

@ MitchellK questo non sta gestendo affatto il contenuto della chiamata http. Se il "titolo della pagina" (qualunque esso sia) è nell'URL, puoi aggiungerlo. In caso contrario, è necessario analizzare l'intera pagina per estrarne il "titolo" (assumendo che tu intenda una pagina html recuperata dall'http). Cerca altre risposte in Stack Overflow o poni quella domanda specifica.
estani

15

Questo si basa su un'ampia disponibilità wget, presente quasi ovunque, anche su Alpine Linux.

wget --server-response --spider --quiet "${url}" 2>&1 | awk 'NR==1{print $2}'

Le spiegazioni sono le seguenti:

--quiet

Disattiva l'output di Wget.

Fonte: pagine man di wget

--spider

[...] non scaricherà le pagine, basta controllare che ci siano. [...]

Fonte: pagine man di wget

--server-response

Stampa le intestazioni inviate dai server HTTP e le risposte inviate dai server FTP.

Fonte: pagine man di wget

Quello di cui non dicono --server-responseè che l'output di queste intestazioni viene stampato sullo standard error (sterr) , quindi la necessità di reindirizzare a stdin.

L'output inviato allo standard input, possiamo reindirizzarlo awkper estrarre il codice di stato HTTP. Quel codice è:

  • il secondo ( $2) gruppo di caratteri non vuoto:{$2}
  • sulla primissima riga dell'intestazione: NR==1

E perché vogliamo stamparlo ... {print $2}.

wget --server-response --spider --quiet "${url}" 2>&1 | awk 'NR==1{print $2}'

1
Ho usato questo con2>&1 | head -1 | awk '{ print $2 }'
Evhz

7

Utilizzare curlper recuperare solo l'intestazione HTTP (non l'intero file) e analizzarlo:

$ curl -I  --stderr /dev/null http://www.google.co.uk/index.html | head -1 | cut -d' ' -f2
200

curl mi dice 200 quando wget dice 404 ... :(
Manu

Il -Iflag fa sì che curl effettui una richiesta HTTP HEAD, che viene trattata separatamente da un normale HTTP GET da alcuni server e può quindi restituire valori diversi. Il comando dovrebbe ancora funzionare senza di esso.
lambshaanxy

4

wget -S -i *file* ti fornirà le intestazioni da ogni URL in un file.

Filtra però grepper il codice di stato in modo specifico.


1

Ho trovato uno strumento "webchk" scritto in Python. Restituisce un codice di stato per un elenco di URL. Https://pypi.org/project/webchk/

L'output è simile a questo:

▶ webchk -i ./dxieu.txt | grep '200'
http://salesforce-case-status.dxi.eu/login ... 200 OK (0.108)
https://support.dxi.eu/hc/en-gb ... 200 OK (0.389)
https://support.dxi.eu/hc/en-gb ... 200 OK (0.401)

Spero che aiuti!


0

A causa di https://mywiki.wooledge.org/BashPitfalls#Non-atomic_writes_with_xargs_-P (output da lavori paralleli a xargsrischio misto), utilizzerei GNU Parallel invece di xargsparallelizzare:

cat url.lst |
  parallel -P0 -q curl -o /dev/null --silent --head --write-out '%{url_effective}: %{http_code}\n' > outfile

In questo caso particolare può essere sicuro da usare xargsperché l'output è così breve, quindi il problema con l'utilizzo xargsè piuttosto che se qualcuno successivamente cambia il codice per fare qualcosa di più grande, non sarà più sicuro. Oppure, se qualcuno legge questa domanda e pensa di poterla sostituire curlcon qualcos'altro, allora potrebbe non essere sicuro.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.