Skript zum Abrufen des HTTP-Statuscodes einer Liste von URLs?


86

Ich habe eine Liste von URLs, die ich überprüfen muss, um festzustellen, ob sie noch funktionieren oder nicht. Ich möchte ein Bash-Skript schreiben, das das für mich erledigt.

Ich benötige nur den zurückgegebenen HTTP-Statuscode, dh 200, 404, 500 usw. Nichts mehr.

BEARBEITEN Beachten Sie, dass ein Problem auftritt , wenn auf der Seite "404 nicht gefunden" angezeigt wird, aber die Meldung "200 OK" zurückgegeben wird. Es ist ein falsch konfigurierter Webserver, aber Sie müssen diesen Fall möglicherweise berücksichtigen.

Weitere Informationen hierzu finden Sie unter Überprüfen, ob eine URL zu einer Seite mit dem Text "404" führt.


2
Um fair zu sein, der "Fehler" meines Skripts tritt nur auf, wenn der Server den HTTP-Code 200 zurückgibt, der Text jedoch "404 nicht gefunden" lautet, was ein sich schlecht verhaltender Webserver ist.
Phil

2
Der Exit-Status von wget ist 0, wenn der Antwortcode 200, 8, wenn 404, 4, wenn 302 war ... Sie können das $? Variable, um auf den Exit-Status des vorherigen Befehls zuzugreifen.
Casey Watson

Antworten:


190

Curl hat dafür eine spezielle Option --write-out:

$ curl -o /dev/null --silent --head --write-out '%{http_code}\n' <url>
200
  • -o /dev/null wirft die übliche Ausgabe weg
  • --silent wirft die Fortschrittsanzeige weg
  • --head macht eine HEAD HTTP-Anfrage anstelle von GET
  • --write-out '%{http_code}\n' druckt den erforderlichen Statuscode

So schließen Sie dies in ein vollständiges Bash-Skript ein:

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

(Leser mit Adleraugen werden feststellen, dass hierfür ein Curl-Prozess pro URL verwendet wird, was zu Gabelungs- und TCP-Verbindungsstrafen führt. Es wäre schneller, wenn mehrere URLs in einem einzigen Curl kombiniert würden, aber es gibt keinen Platz, um die monströse Wiederholung aufzuschreiben von Optionen, die Curl benötigt, um dies zu tun.)


Sehr schön. Kann ich diesen Befehl für jede URL in meiner Datei ausführen?
Manu

1
@Manu: Ja, ich habe meine Antwort bearbeitet, um eine Möglichkeit zum Einschließen des Curl-Befehls aufzuzeigen. Es wird davon ausgegangen, dass url-list.txt eine URL pro Zeile enthält.
Phil

1
Ich weiß nicht, warum Skript von oben andswer mich immer 000 in der Ausgabe bekommen, aber wenn ich Befehl nur einmal ohne Schleife ausführe, funktioniert es ...
Karol F

1
@KarolFiturski Ich hatte das gleiche Problem (das Sie wahrscheinlich seitdem behoben haben, aber nur für den Fall, dass jemand anderes darüber stolpert ...), in meinem Fall hatte ich Wagenrückläufe an den Zeilenende meiner Eingabedatei, was dazu führte, dass die URLs wie folgt waren http://example.com/\rbeim Durchlaufen der Schleife
Jordan Robinson

1
Ich hatte dieses Problem und konnte es beheben, indem ich die Zeilenende vom Windows-Typ auf den Linux-Typ umstellte.
Tristan

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

druckt nur den Statuscode für Sie


9
+1 Zeigt mehrere Codes an, wenn eine URL umgeleitet wird, jeweils in einer neuen Zeile.
Ashfame

Musste die --spider loswerden, damit sie mit der Anfrage funktioniert, die ich machen wollte, aber sie funktioniert.
Amitavk

29

Erweiterung der Antwort von Phil. Das Hinzufügen von Parallelität ist ein Kinderspiel, wenn Sie xargs für den Aufruf verwenden.

Hier der Code:

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

-n1 : Verwenden Sie nur einen Wert (aus der Liste) als Argument für den Curl-Aufruf

-P10 : Halten Sie jederzeit 10 Curl-Prozesse am Leben (dh 10 parallele Verbindungen)

Überprüfen Sie den write_outParameter im Handbuch von curl auf weitere Daten, die Sie damit extrahieren können (Zeiten usw.).

Falls es jemandem hilft, ist dies der Anruf, den ich gerade verwende:

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

Es gibt nur eine Reihe von Daten in eine CSV-Datei aus, die in jedes Office-Tool importiert werden kann.


2
Parallelität, Dateieingabe und CSV. Genau das, wonach ich gesucht habe.
Agey

Genial, machte meinen Tag.
xlttj

Das ist großartig, genau das, wonach ich gesucht habe, danke, Sir. Eine Frage, wie könnte man den Seitentitel der Seite in die CSV-Ergebnisse aufnehmen?
MitchellK

@estani - stackoverflow.com/users/1182464/estani Wie könnte man den Seitentitel einer Seite in die CSV-Datei aufnehmen ? Entschuldigung für das Umbuchen, ich habe vergessen, Sie zu markieren, damit Sie über diese Frage benachrichtigt werden. Danke vielmals.
MitchellK

@MitchellK Dies behandelt den Inhalt des http-Aufrufs überhaupt nicht. Wenn der "Seitentitel" (was auch immer das ist) in der URL enthalten ist, können Sie ihn hinzufügen. Wenn nicht, müssen Sie die gesamte Seite analysieren, um den "Titel" zu extrahieren (vorausgesetzt, Sie meinen eine HTML-Seite, die vom http abgerufen wird). Suchen Sie beim Stapelüberlauf nach anderen Antworten oder stellen Sie diese spezielle Frage.
Estani

13

Dies beruht auf weit verbreiteten wget, fast überall vorhandenen, sogar auf Alpine Linux.

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

Die Erklärungen lauten wie folgt:

--quiet

Schalten Sie die Ausgabe von Wget aus.

Quelle - wget Manpages

--spider

[...] die Seiten werden nicht heruntergeladen, sondern nur überprüft, ob sie vorhanden sind. [...]

Quelle - wget Manpages

--server-response

Drucken Sie die von HTTP-Servern gesendeten Header und die von FTP-Servern gesendeten Antworten.

Quelle - wget Manpages

Was sie nicht sagen, --server-responseist, dass diese Header-Ausgaben auf Standardfehler (sterr) gedruckt werden , daher muss auf stdin umgeleitet werden .

Die Ausgabe, die an die Standardeingabe gesendet wird, kann weitergeleitet werden awk, um den HTTP-Statuscode zu extrahieren. Dieser Code lautet:

  • die zweite ( $2) nicht leere Gruppe von Zeichen:{$2}
  • in der allerersten Zeile der Kopfzeile: NR==1

Und weil wir es drucken möchten ... {print $2}.

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

1
Ich habe dieses mit2>&1 | head -1 | awk '{ print $2 }'
Evhz

7

Verwenden Sie curldiese Option, um nur den HTTP-Header (nicht die gesamte Datei) abzurufen und zu analysieren:

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

Curl sagt mir 200, wenn wget 404 sagt ... :(
Manu

Das -IFlag bewirkt, dass Curl eine HTTP-HEAD-Anforderung ausführt, die von einigen Servern getrennt von einem normalen HTTP-GET behandelt wird und daher unterschiedliche Werte zurückgeben kann. Der Befehl sollte weiterhin ohne ihn funktionieren.
Lambshaanxy

4

wget -S -i *file* Sie erhalten die Header von jeder URL in einer Datei.

Filtern Sie jedoch grepspeziell nach dem Statuscode.


1

Ich habe ein in Python geschriebenes Tool "webchk" gefunden. Gibt einen Statuscode für eine Liste von URLs zurück. Https://pypi.org/project/webchk/

Die Ausgabe sieht folgendermaßen aus:

 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)

Hoffentlich hilft das!


0

Aufgrund von https://mywiki.wooledge.org/BashPitfalls#Non-atomic_writes_with_xargs_-P (Ausgabe von parallelen Jobs bei xargsgemischten Risiken) würde ich GNU Parallel verwenden, anstatt xargszu parallelisieren:

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

In diesem speziellen Fall kann die Verwendung sicher sein, xargsda die Ausgabe so kurz ist. Das Problem bei der Verwendung xargsbesteht daher eher darin, dass sie später nicht mehr sicher ist, wenn jemand später den Code ändert, um etwas Größeres zu tun. Oder wenn jemand diese Frage liest und glaubt, sie durch curletwas anderes ersetzen zu können, ist dies möglicherweise auch nicht sicher.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.