Скрипт для отримання коду стану HTTP списку URL-адрес?


87

У мене є список URL-адрес, які мені потрібно перевірити, чи вони все ще працюють чи ні. Я хотів би написати сценарій bash, який робить це для мене.

Мені потрібен лише повернутий код стану HTTP, тобто 200, 404, 500 тощо. Нічого більше.

РЕДАГУВАТИ Зверніть увагу, що є проблема, якщо на сторінці написано "404 не знайдено", але повертається повідомлення 200 OK Це неправильно налаштований веб-сервер, але, можливо, вам доведеться розглянути цей випадок.

Докладніше про це див. У розділі Перевірка переходу URL-адреси на сторінку, що містить текст "404"


2
Чесно кажучи, "помилка" мого сценарію - це лише тоді, коли сервер повертає HTTP-код 200, але в основному тексті написано "404 не знайдено", що є неправильним веб-сервером.
Філ

2
Статус виходу wget буде 0, якщо код відповіді був 200, 8 якщо 404, 4 якщо 302 ... Ви можете використовувати $? змінна для доступу до статусу виходу попередньої команди.
Кейсі Уотсон,

Відповіді:


194

Curl має певний варіант --write-out, для цього:

$ curl -o /dev/null --silent --head --write-out '%{http_code}\n' <url>
200
  • -o /dev/null викидає звичайний вихід
  • --silent викидає індикатор прогресу
  • --head робить запит HEAD HTTP, замість GET
  • --write-out '%{http_code}\n' друкує необхідний код стану

Щоб обернути це повним сценарієм Bash:

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

(Орлові очі читачі помітять, що тут використовується один процес закручування для кожної URL-адреси, що передбачає покарання за вилку та TCP. Це було б швидше, якби декілька URL-адрес були об’єднані в один завиток, але немає місця для випису монстрового повторення варіантів, для яких потрібно зробити curl.)


Дуже хороша. Чи можу я виконати цю команду на кожній URL-адресі у своєму файлі?
Ману

1
@Manu: Так, я відредагував свою відповідь, щоб показати один із можливих способів завершення команди curl. Він передбачає, що url-list.txt містить одну URL-адресу на рядок.
Філ

1
Я не знаю, чому скрипт зверху andswer завжди отримує мені 000 на виході, але коли я запускаю команду лише один раз без циклу, це працює ...
Кароль F

1
@KarolFiturski У мене була та сама проблема (яку ви, мабуть, з тих пір виправили, але на випадок, якщо хтось інший натрапить на це ...) у моєму випадку у мене були повернення каретки в кінці рядка мого вхідного файлу, через що URL-адреси були схожими http://example.com/\rпри проходженні петлі
Джордан Робінсон

1
У мене була ця проблема, і я зміг її виправити, переключивши рядок, що закінчується з типу Windows на тип Linux.
Трістан

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

друкує лише код стану для вас


9
+1 Показує кілька кодів при перенаправленні URL-адреси, кожен у новому рядку.
Ashfame

Довелося позбутися --spider, щоб він працював із запитом, який я намагався зробити, але працює.
amitavk

30

Розширюючи відповідь, вже надану Філом. Додавання паралелізму до нього - це не простий результат у bash, якщо ви використовуєте xargs для дзвінка.

Ось код:

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

-n1 : використовуйте лише одне значення (зі списку) як аргумент для виклику curl

-P10 : Тримайте 10 процесів завивання в будь-який час (тобто 10 паралельних з'єднань)

Перевірте write_out параметр у посібнику з curl, щоб дізнатись більше даних, які ви можете отримати з його допомогою (час і т.д.).

Якщо комусь це допоможе, це дзвінок, який я зараз використовую:

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

Він просто видає купу даних у файл CSV, який можна імпортувати в будь-який офісний інструмент.


2
Паралельність, введення файлів та csv. Саме те, що я шукав.
Agey

Блискуче, зробило мій день.
xlttj

Це чудово, саме те, що я шукав, дякую, сер. Одне питання, як можна включити заголовок сторінки в результати CSV?
MitchellK

@estani - stackoverflow.com/users/1182464/estani як би один включати отримання заголовка сторінки сторінки в файл .csv. Вибачте за репост, забув позначити вас тегом, щоб отримати сповіщення про це питання. Дуже дякую.
MitchellK

@MitchellK це взагалі не обробляє вміст виклику http. Якщо "заголовок сторінки" (який би він не був) міститься в URL-адресі, ви можете додати його. Якщо ні, вам потрібно проаналізувати всю сторінку, щоб витягти її "заголовок" (припускаючи, що ви маєте на увазі HTML-сторінку, отриману за допомогою http). Шукайте інші відповіді при переповненні стека або задайте це конкретне питання.
estani

15

Це спирається на широко доступні wget, майже всюди, навіть на Alpine Linux.

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

Пояснення такі:

--quiet

Вимкніть вихід Wget.

Джерело - wget man pages

--spider

[...] він не буде завантажувати сторінки, просто перевірте, чи є вони там. [...]

Джерело - wget man pages

--server-response

Роздрукуйте заголовки, надіслані HTTP-серверами, та відповіді, надіслані FTP-серверами.

Джерело - wget man pages

Що вони не говорять про --server-responseте, що ці заголовки виводяться із стандартною помилкою (sterr) , отже, необхідність перенаправлення на stdin.

Вихідні дані надсилаються на стандартний вхід, ми можемо направити його awkдля вилучення коду стану HTTP. Цей код:

  • друга ( $2) непуста група символів:{$2}
  • у першому рядку заголовка: NR==1

І тому , що ми хочемо надрукувати його ... {print $2}.

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

1
Я використовував цей з2>&1 | head -1 | awk '{ print $2 }'
Evhz

7

Використовуйте curlдля отримання лише заголовка HTTP (а не цілого файлу) та аналізу його:

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

curl каже мені 200, коли wget каже 404 ... :(
Ману

-I прапорі причини згорнутися , щоб зробити запит HTTP HEAD, який обробляється окремо від нормального HTTP GET деяких серверів і таким чином повертати різні значення. Команда все одно повинна працювати без неї.
lambshaanxy

4

wget -S -i *file* отримає заголовки з кожної URL-адреси у файлі.

Фільтруйте, однак, grepспеціально код стану.


1

Я знайшов інструмент "webchk", написаний на Python. Повертає код стану для списку URL-адрес. Https://pypi.org/project/webchk/

Результат виглядає так:

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

Сподіваюся, це допоможе!


0

Завдяки https://mywiki.wooledge.org/BashPitfalls#Non-atomic_writes_with_xargs_-P (вихід з паралельних завдань із xargsризиком змішування), я б використовував GNU Parallel замість того, xargsщоб паралелізувати:

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

У цьому конкретному випадку це може бути безпечним у використанні, xargsоскільки висновок настільки короткий, тому проблема використання xargsполягає швидше в тому, що якщо хтось пізніше змінить код, щоб зробити щось більше, це більше не буде безпечним. Або якщо хтось читає це питання і думає, що може замінити curlчимось іншим, то це також може бути не безпечно.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.