Script pour obtenir le code d'état HTTP d'une liste d'urls?

87

J'ai une liste d'URL que je dois vérifier, pour voir si elles fonctionnent toujours ou non. J'aimerais écrire un script bash qui le fasse pour moi.

Je n'ai besoin que du code d'état HTTP renvoyé, c'est-à-dire 200, 404, 500 et ainsi de suite. Rien de plus.

EDIT Notez qu'il y a un problème si la page dit "404 non trouvé" mais renvoie un message 200 OK. C'est un serveur Web mal configuré, mais vous devrez peut-être considérer ce cas.

Pour en savoir plus, consultez Vérifier si une URL mène à une page contenant le texte "404"

Manu
la source
2
Pour être honnête, le "bug" de mon script se produit uniquement lorsque le serveur renvoie le code HTTP 200 mais le corps du texte dit "404 not found", ce qui est un serveur Web qui se comporte mal.
Phil
2
Le statut de sortie de wget sera 0 si le code de réponse était 200, 8 si 404, 4 si 302 ... Vous pouvez utiliser le $? variable pour accéder à l'état de sortie de la commande précédente.
Casey Watson

Réponses:

194

Curl a une option spécifique --write-out, pour cela:

$ curl -o /dev/null --silent --head --write-out '%{http_code}\n' <url>
200
  • -o /dev/null jette la sortie habituelle
  • --silent jette la jauge de progression
  • --head fait une requête HTTP HEAD au lieu de GET
  • --write-out '%{http_code}\n' imprime le code d'état requis

Pour résumer cela dans un script Bash complet:

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

(Les lecteurs aux yeux d'aigle remarqueront que cela utilise un processus curl par URL, ce qui impose des pénalités de fork et de connexion TCP. Ce serait plus rapide si plusieurs URL étaient combinées dans une seule boucle, mais il n'y a pas d'espace pour écrire la répétition monstre des options dont curl a besoin pour ce faire.)

Phil
la source
Très agréable. Puis-je exécuter cette commande sur chaque URL de mon fichier?
Manu
1
@Manu: Oui, j'ai modifié ma réponse pour montrer une façon possible de terminer la commande curl. Il suppose que url-list.txt contient une URL par ligne.
Phil
1
Je ne sais pas pourquoi le script d'en haut et la réponse me donnent toujours 000 dans la sortie, mais quand je n'exécute la commande qu'une seule fois sans boucle, cela fonctionne ...
Karol F
1
@KarolFiturski J'ai eu le même problème (que vous avez probablement résolu depuis, mais juste au cas où quelqu'un d'autre trébucherait sur cela ...) dans mon cas, j'avais des retours chariot aux extrémités de mon fichier d'entrée, ce qui faisait que les URL ressemblaient à http://example.com/\ren passant par la boucle
Jordan Robinson
1
J'ai eu ce problème et j'ai pu le résoudre en basculant la fin de ligne du type Windows vers le type Linux.
Tristan
38
wget --spider -S "http://url/to/be/checked" 2>&1 | grep "HTTP/" | awk '{print $2}'

imprime uniquement le code d'état pour vous

user551168
la source
9
+1 Affiche plusieurs codes lorsqu'une URL est redirigée, chacun à une nouvelle ligne.
Ashfame
J'ai dû me débarrasser de l'araignée pour que cela fonctionne avec la demande que j'essayais de faire, mais cela fonctionne.
amitavk
30

Prolongeant la réponse déjà fournie par Phil. Ajouter du parallélisme à celui-ci est une évidence dans bash si vous utilisez xargs pour l'appel.

Voici le code:

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

-n1 : n'utilise qu'une seule valeur (de la liste) comme argument à l'appel curl

-P10 : Gardez 10 processus curl actifs à tout moment (soit 10 connexions parallèles)

Vérifiez le write_outparamètre dans le manuel de curl pour plus de données que vous pouvez extraire en l'utilisant (heures, etc.).

Au cas où cela aiderait quelqu'un, voici l'appel que j'utilise actuellement:

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

Il génère simplement un tas de données dans un fichier csv qui peut être importé dans n'importe quel outil de bureau.

estani
la source
2
Parallélisme, entrée de fichier et csv. Exactement ce que je cherchais.
Agey
Brillant, a fait ma journée.
xlttj
C'est génial, exactement ce que je cherchais, merci monsieur. Une question, comment pourrait-on inclure le titre de la page de la page dans les résultats csv?
MitchellK
@estani - stackoverflow.com/users/1182464/estani comment pourrait-on inclure l'obtention du titre de page d'une page dans le fichier .csv. Désolé pour la republication, j'ai oublié de vous taguer afin que vous soyez informé de cette question. Merci beaucoup.
MitchellK
@MitchellK cela ne gère pas du tout le contenu de l'appel http. Si le "titre de la page" (quel qu'il soit) est dans l'url, vous pouvez l'ajouter. Sinon, vous devez analyser la page entière pour en extraire le "titre" (en supposant que vous vouliez dire une page html récupérée par le http). Recherchez d'autres réponses au débordement de pile ou posez cette question spécifique.
estani le
15

Celui-ci repose sur une diffusion largement disponible wget, présente presque partout, même sur Alpine Linux.

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

Les explications sont les suivantes:

--quiet

Désactivez la sortie de Wget.

Source - pages de manuel wget

--spider

[...] il ne téléchargera pas les pages, il suffit de vérifier qu'elles sont là. [...]

Source - pages de manuel wget

--server-response

Imprimez les en-têtes envoyés par les serveurs HTTP et les réponses envoyées par les serveurs FTP.

Source - pages de manuel wget

Ce qu'ils ne disent pas, --server-responsec'est que ces en-têtes sont affichés en erreur standard (sterr) , d'où la nécessité de rediriger vers stdin.

La sortie envoyée à l'entrée standard, nous pouvons la diriger vers awkpour extraire le code d'état HTTP. Ce code est:

  • le deuxième ( $2) groupe de caractères non vide:{$2}
  • sur la toute première ligne de l'en-tête: NR==1

Et parce que nous voulons imprimer ... {print $2}.

wget --server-response --spider --quiet "${url}" 2>&1 | awk 'NR==1{print $2}'
Salathiel Genèse
la source
1
J'ai utilisé celui-ci avec2>&1 | head -1 | awk '{ print $2 }'
Evhz
7

Utilisez curlpour récupérer uniquement l'en-tête HTTP (pas le fichier entier) et l'analyser:

$ curl -I  --stderr /dev/null http://www.google.co.uk/index.html | head -1 | cut -d' ' -f2
200
dogbane
la source
curl me dit 200 quand wget dit 404 ... :(
Manu
L' -Iindicateur amène curl à faire une requête HTTP HEAD, qui est traitée séparément d'un HTTP GET normal par certains serveurs et peut donc renvoyer des valeurs différentes. La commande devrait toujours fonctionner sans elle.
lambshaanxy
4

wget -S -i *file* vous obtiendrez les en-têtes de chaque URL dans un fichier.

Filtrez cependant greppour le code d'état spécifiquement.

colinross
la source
1

J'ai trouvé un outil "webchk" écrit en Python. Renvoie un code d'état pour une liste d'urls. Https://pypi.org/project/webchk/

La sortie ressemble à ceci:

▶ 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)

J'espère que ça t'as aidé!

Yura Loginov
la source
0

En raison de https://mywiki.wooledge.org/BashPitfalls#Non-atomic_writes_with_xargs_-P (sortie de travaux parallèles dans les xargsrisques d'être mélangés), j'utiliserais GNU Parallel au lieu de xargsparalléliser:

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

Dans ce cas particulier, il peut être sûr d'utiliser xargsparce que la sortie est si courte, donc le problème avec l'utilisation xargsest plutôt que si quelqu'un change plus tard le code pour faire quelque chose de plus grand, il ne sera plus sûr. Ou si quelqu'un lit cette question et pense qu'il peut la remplacer curlpar autre chose, cela peut également ne pas être sûr.

Ole Tange
la source