Script untuk mendapatkan kode status HTTP dari daftar url?

89

Saya memiliki daftar URL yang perlu saya periksa, untuk melihat apakah masih berfungsi atau tidak. Saya ingin menulis skrip bash yang melakukannya untuk saya.

Saya hanya perlu kode status HTTP yang dikembalikan, yaitu 200, 404, 500, dan seterusnya. Tidak ada lagi.

EDIT Perhatikan bahwa ada masalah jika halaman mengatakan "404 tidak ditemukan" tetapi mengembalikan pesan 200 OK. Ini adalah server web yang salah dikonfigurasi, tetapi Anda mungkin harus mempertimbangkan kasus ini.

Untuk lebih lanjut tentang ini, lihat Periksa apakah URL menuju ke halaman yang berisi teks "404"

Manu
sumber
2
Agar adil, "bug" skrip saya hanya ketika server mengembalikan kode HTTP 200 tetapi teks isi mengatakan "404 tidak ditemukan", yang merupakan server web yang berperilaku tidak semestinya.
Phil
2
Status keluar wget akan menjadi 0 jika kode respon adalah 200, 8 jika 404, 4 jika 302 ... Anda dapat menggunakan $? variabel untuk mengakses status keluar dari perintah sebelumnya.
Casey Watson

Jawaban:

198

Curl memiliki opsi khusus --write-out, untuk ini:

$ curl -o /dev/null --silent --head --write-out '%{http_code}\n' <url>
200
  • -o /dev/null membuang keluaran biasa
  • --silent membuang pengukur kemajuan
  • --head membuat permintaan HTTP HEAD, bukan GET
  • --write-out '%{http_code}\n' mencetak kode status yang diperlukan

Untuk menyelesaikan ini dalam skrip Bash lengkap:

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

(Pembaca bermata elang akan melihat bahwa ini menggunakan satu proses curl per URL, yang memberlakukan hukuman fork dan koneksi TCP. Akan lebih cepat jika beberapa URL digabungkan dalam satu curl, tetapi tidak ada ruang untuk menulis pengulangan monsterous opsi yang diperlukan curl untuk melakukan ini.)

Phil
sumber
Sangat bagus. Bisakah saya menjalankan perintah itu di setiap url di file saya?
Manu
1
@Manu: Ya, saya telah mengedit jawaban saya untuk menunjukkan satu cara yang mungkin untuk menyelesaikan perintah curl. Ini mengasumsikan url-list.txt berisi satu URL per baris.
Phil
1
Saya tidak tahu mengapa skrip dari atas dan selalu mendapatkan output 000, tetapi ketika saya menjalankan perintah hanya sekali tanpa loop, itu berfungsi ...
Karol F
1
@KarolFiturski Saya memiliki masalah yang sama (yang mungkin sudah Anda perbaiki tetapi kalau-kalau ada orang lain yang tersandung ini ...) dalam kasus saya, saya memiliki pengembalian kereta di ujung baris file input saya, menyebabkan url menjadi seperti http://example.com/\rsaat melalui loop
Jordan Robinson
1
Saya mengalami masalah ini dan saya dapat memperbaikinya dengan mengalihkan akhir baris dari tipe Windows ke tipe Linux.
Tristan
38
wget --spider -S "http://url/to/be/checked" 2>&1 | grep "HTTP/" | awk '{print $2}'

mencetak hanya kode status untuk Anda

pengguna551168
sumber
9
+1 Menunjukkan beberapa kode ketika url diarahkan, masing-masing di baris baru.
Ashfame
Harus menyingkirkan --spider agar bekerja dengan permintaan yang saya coba buat, tetapi berhasil.
amitavk
30

Memperluas jawaban yang sudah diberikan oleh Phil. Menambahkan paralelisme ke dalamnya adalah hal yang mudah jika Anda menggunakan xargs untuk panggilan tersebut.

Berikut kodenya:

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

-n1 : gunakan hanya satu nilai (dari daftar) sebagai argumen untuk panggilan curl

-P10 : Jaga 10 proses curl tetap hidup setiap saat (yaitu 10 koneksi paralel)

Periksa write_outparameter di manual curl untuk mengetahui lebih banyak data yang dapat Anda ekstrak menggunakannya (waktu, dll).

Jika itu membantu seseorang, inilah panggilan yang sedang saya gunakan:

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

Itu hanya mengeluarkan banyak data ke dalam file csv yang dapat diimpor ke alat kantor apa pun.

estani
sumber
2
Paralelisme, masukan file dan csv. Persis apa yang saya cari.
Agey
Brilian, membuat hariku menyenangkan.
xlttj
Ini luar biasa, hanya yang saya cari, terima kasih tuan. Satu pertanyaan, bagaimana seseorang bisa memasukkan judul halaman dalam hasil csv?
MitchellK
@estani - stackoverflow.com/users/1182464/estani bagaimana cara memasukkan judul halaman halaman ke dalam file .csv. Maaf untuk repost, lupa untuk menandai Anda sehingga Anda akan mendapatkan pemberitahuan tentang pertanyaan ini. Terimakasih banyak.
MitchellK
@MitchellK ini sama sekali tidak menangani konten panggilan http. Jika "judul halaman" (apapun itu) ada di url, maka Anda dapat menambahkannya. Jika tidak, Anda perlu mengurai seluruh halaman untuk mengekstrak "judul" -nya (dengan asumsi yang Anda maksud adalah halaman html yang diambil oleh http). Cari jawaban lain di stack overflow atau ajukan pertanyaan spesifik itu.
estani
17

Ini bergantung pada ketersediaan luas wget, hadir hampir di mana-mana, bahkan di Alpine Linux.

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

Penjelasannya sebagai berikut:

--quiet

Matikan keluaran Wget.

Sumber - halaman manual wget

--spider

[...] itu tidak akan mengunduh halaman, cukup periksa apakah halaman itu ada. [...]

Sumber - halaman manual wget

--server-response

Cetak header yang dikirim oleh server HTTP dan tanggapan yang dikirim oleh server FTP.

Sumber - halaman manual wget

Apa yang tidak mereka katakan --server-responseadalah bahwa output header tersebut dicetak ke kesalahan standar (sterr) , sehingga perlu dialihkan ke stdin.

Output dikirim ke input standar, kita dapat menyalurkannya ke awkuntuk mengekstrak kode status HTTP. Kode itu adalah:

  • $2kelompok karakter kedua ( ) tidak kosong:{$2}
  • di baris pertama tajuk: NR==1

Dan karena kami ingin mencetaknya… {print $2}.

wget --server-response --spider --quiet "${url}" 2>&1 | awk 'NR==1{print $2}'
Salathiel Genèse
sumber
1
Saya menggunakan yang ini dengan2>&1 | head -1 | awk '{ print $2 }'
Evhz
7

Gunakan curluntuk mengambil HTTP-header saja (bukan seluruh file) dan parsing:

$ curl -I  --stderr /dev/null http://www.google.co.uk/index.html | head -1 | cut -d' ' -f2
200
dogbane
sumber
curl memberi tahu saya 200 ketika wget mengatakan 404 ... :(
Manu
The -Ipenyebab bendera meringkuk untuk membuat permintaan HTTP HEAD, yang diperlakukan secara terpisah dari normal HTTP GET oleh beberapa server dan dengan demikian dapat kembali nilai-nilai yang berbeda. Perintah harus tetap berfungsi tanpanya.
lambshaanxy
4

wget -S -i *file* akan memberi Anda header dari setiap url dalam sebuah file.

Filter meskipun grepuntuk kode status secara khusus.

colinross
sumber
1

Saya menemukan alat "webchk" yang ditulis dengan Python. Mengembalikan kode status untuk daftar url. Https://pypi.org/project/webchk/

Outputnya terlihat seperti ini:

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

Semoga membantu!

Yura Loginov
sumber
0

Karena https://mywiki.wooledge.org/BashPitfalls#Non-atomic_writes_with_xargs_-P (keluaran dari pekerjaan paralel dalam xargsrisiko tercampur), saya akan menggunakan GNU Parallel alih-alih xargsmemparalelkan:

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

Dalam kasus khusus ini mungkin aman untuk digunakan xargskarena outputnya sangat pendek, jadi masalah dengan menggunakan xargsadalah jika seseorang kemudian mengubah kode untuk melakukan sesuatu yang lebih besar, itu tidak akan aman lagi. Atau jika seseorang membaca pertanyaan ini dan berpikir dia dapat mengganti curldengan sesuatu yang lain, maka itu mungkin juga tidak aman.

Ole Tange
sumber