Tập lệnh để lấy mã trạng thái HTTP của một danh sách các url?


87

Tôi có một danh sách các URL mà tôi cần kiểm tra để xem chúng có còn hoạt động hay không. Tôi muốn viết một kịch bản bash làm điều đó cho tôi.

Tôi chỉ cần mã trạng thái HTTP trả về, tức là 200, 404, 500, v.v. Chỉ có bấy nhiêu thôi.

CHỈNH SỬA Lưu ý rằng có sự cố nếu trang cho biết "Không tìm thấy 404" nhưng trả về thông báo 200 OK. Đó là một máy chủ web được định cấu hình sai, nhưng bạn có thể phải xem xét trường hợp này.

Để biết thêm về điều này, hãy xem Kiểm tra xem một URL có chuyển đến trang có chứa văn bản "404" hay không


2
Công bằng mà nói, "lỗi" của tập lệnh của tôi chỉ xảy ra khi máy chủ trả về mã HTTP 200 nhưng nội dung văn bản cho biết "không tìm thấy 404", đó là một máy chủ web hoạt động sai.
Phil

2
Trạng thái thoát của wget sẽ là 0 nếu mã phản hồi là 200, 8 nếu 404, 4 nếu 302 ... Bạn có thể sử dụng $? biến để truy cập trạng thái thoát của lệnh trước đó.
Casey Watson

Câu trả lời:


194

Curl có một tùy chọn cụ thể --write-out, cho điều này:

$ curl -o /dev/null --silent --head --write-out '%{http_code}\n' <url>
200
  • -o /dev/null vứt bỏ đầu ra thông thường
  • --silent ném đồng hồ đo tiến trình đi
  • --head thực hiện một yêu cầu HEAD HTTP, thay vì GET
  • --write-out '%{http_code}\n' in mã trạng thái bắt buộc

Để kết thúc điều này trong một tập lệnh Bash hoàn chỉnh:

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

(Người đọc có đôi mắt đại bàng sẽ nhận thấy rằng quy trình này sử dụng một quy trình cuộn cho mỗi URL, quy trình này áp dụng các hình phạt về fork và kết nối TCP. Sẽ nhanh hơn nếu nhiều URL được kết hợp trong một cuộn duy nhất, nhưng không có không gian để viết ra sự lặp lại độc hại trong số các tùy chọn cuộn tròn yêu cầu để thực hiện điều này.)


Rất đẹp. Tôi có thể thực hiện lệnh đó trên mọi url trong tệp của mình không?
Manu

1
@Manu: Có, tôi đã chỉnh sửa câu trả lời của mình để hiển thị một cách khả thi để gói lệnh curl. Nó giả sử url-list.txt chứa một URL trên mỗi dòng.
Phil

1
Tôi không biết tại sao kịch bản từ trên andswer luôn làm cho tôi 000 trong đầu ra, nhưng khi tôi chạy lệnh một lần duy nhất mà không cần vòng lặp nó hoạt động ...
Karol F

1
@KarolFiturski Tôi đã gặp vấn đề tương tự (có thể bạn đã khắc phục sự cố này nhưng đề phòng bất kỳ ai khác tình cờ gặp phải vấn đề này ...) trong trường hợp của tôi, tôi có ký tự xuống dòng ở cuối dòng của tệp đầu vào của mình, khiến các url giống như http://example.com/\rkhi đi qua vòng lặp
Jordan Robinson

1
Tôi gặp sự cố này và tôi đã có thể khắc phục bằng cách chuyển dòng kết thúc từ loại Windows sang loại Linux.
Tristan

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

chỉ in mã trạng thái cho bạn


9
+1 Hiển thị nhiều mã khi url được chuyển hướng, mỗi mã ở dòng mới.
Ashfame

Phải loại bỏ --spider để nó hoạt động với yêu cầu mà tôi đang cố gắng thực hiện, nhưng hoạt động.
amitavk

30

Mở rộng câu trả lời đã được cung cấp bởi Phil. Thêm song song với nó là không có trí tuệ trong bash nếu bạn sử dụng xargs cho cuộc gọi.

Đây là mã:

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

-n1 : chỉ sử dụng một giá trị (từ danh sách) làm đối số cho lệnh gọi curl

-P10 : Giữ cho 10 quy trình cuộn tròn tồn tại bất kỳ lúc nào (tức là 10 kết nối song song)

Kiểm tra write_outthông số trong hướng dẫn sử dụng curl để biết thêm dữ liệu mà bạn có thể trích xuất bằng cách sử dụng nó (lần, v.v.).

Trong trường hợp nó giúp ai đó thì đây là cuộc gọi mà tôi hiện đang sử dụng:

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

Nó chỉ xuất một loạt dữ liệu vào một tệp csv có thể được nhập vào bất kỳ công cụ văn phòng nào.


2
Song song, đầu vào tệp và csv. Chính xác những gì tôi đang tìm kiếm.
Agey

Rực rỡ, đã làm nên ngày của tôi.
xlttj

Điều này thật tuyệt vời, đúng như những gì tôi đang tìm kiếm, cảm ơn ông. Một câu hỏi, làm thế nào người ta có thể đưa tiêu đề trang của trang vào kết quả csv?
MitchellK

@estani - stackoverflow.com/users/1182464/estani làm cách nào để đưa tiêu đề trang của một trang vào tệp .csv. Xin lỗi vì đã đăng lại, quên gắn thẻ bạn nên bạn sẽ nhận được thông báo về câu hỏi này. Cảm ơn nhiều.
MitchellK

@MitchellK đây không phải là xử lý nội dung của lệnh gọi http. Nếu "tiêu đề trang" (bất cứ điều gì đó) nằm trong url, thì bạn có thể thêm nó. Nếu không, bạn cần phải phân tích cú pháp toàn bộ trang để trích xuất "tiêu đề" của nó (giả sử ý bạn là một trang html được lấy bởi http). Tìm kiếm câu trả lời khác tại tràn ngăn xếp hoặc hỏi câu hỏi cụ thể đó.
estani

15

Điều này phụ thuộc vào việc phổ biến rộng rãi wget, hiện diện ở hầu hết mọi nơi, ngay cả trên Alpine Linux.

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

Các giải thích như sau:

--quiet

Tắt đầu ra của Wget.

Nguồn - wget man trang

--spider

[...] nó sẽ không tải xuống các trang, chỉ cần kiểm tra xem chúng có ở đó không. [...]

Nguồn - wget man trang

--server-response

In tiêu đề do máy chủ HTTP gửi và phản hồi do máy chủ FTP gửi.

Nguồn - wget man trang

Những gì họ không nói về --server-responselà đầu ra các tiêu đề đó được in thành lỗi tiêu chuẩn (sterr) , do đó cần phải chuyển hướng đến stdin.

Đầu ra được gửi đến đầu vào tiêu chuẩn, chúng tôi có thể chuyển nó đến awkđể trích xuất mã trạng thái HTTP. Mã đó là:

  • $2nhóm ký tự không trống ( ) thứ hai :{$2}
  • trên dòng đầu tiên của tiêu đề: NR==1

Và bởi vì chúng tôi muốn in nó ... {print $2}.

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

1
Tôi đã sử dụng cái này với2>&1 | head -1 | awk '{ print $2 }'
Evhz

7

Sử dụng curlđể chỉ tìm nạp tiêu đề HTTP (không phải toàn bộ tệp) và phân tích cú pháp:

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

curl nói với tôi 200 khi wget nói 404 ... :(
Manu

Các -Inguyên nhân cờ cuộn tròn để tạo ra một yêu cầu HTTP HEAD, mà được xử lý riêng rẽ với một bình thường HTTP GET bởi một số máy chủ và do đó có thể trở lại giá trị khác nhau. Lệnh sẽ vẫn hoạt động mà không có nó.
lambshaanxy

4

wget -S -i *file* sẽ giúp bạn nhận được các tiêu đề từ mỗi url trong một tệp.

Lọc mặc dù grepcho mã trạng thái cụ thể.


1

Tôi đã tìm thấy một công cụ "webchk" được viết bằng Python. Trả về mã trạng thái cho danh sách các url. Https://pypi.org/project/webchk/

Đầu ra giống như sau:

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

Hy vọng rằng sẽ giúp!


0

Do https://mywiki.wooledge.org/BashPitfalls#Non-atomic_writes_with_xargs_-P (đầu ra từ các công việc song song có xargsrủi ro bị trộn lẫn), tôi sẽ sử dụng GNU Parallel thay vì xargssong song:

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

Trong trường hợp cụ thể này, nó có thể an toàn để sử dụng xargsvì đầu ra quá ngắn, vì vậy vấn đề khi sử dụng xargslà nếu sau này có người thay đổi mã để làm điều gì đó lớn hơn, nó sẽ không còn an toàn nữa. Hoặc nếu ai đó đọc câu hỏi này và nghĩ rằng anh ta có thể thay thế curlbằng thứ khác, thì điều đó cũng có thể không an toàn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.