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

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

Мне нужен только возвращенный код состояния HTTP, то есть 200, 404, 500 и так далее. Ничего более.

РЕДАКТИРОВАТЬ Обратите внимание, что существует проблема, если на странице написано "404 не найден", но возвращает сообщение 200 OK. Это неправильно настроенный веб-сервер, но вам, возможно, придется рассмотреть этот случай.

Подробнее об этом см. В разделе " Проверка перехода URL-адреса на страницу, содержащую текст"404"".

9 ответов

Решение

У Curl есть особая опция, --write-out, за это:

$ curl -o /dev/null --silent --head --write-out '%{http_code}\n' <url>
200
  • -o /dev/null выбрасывает обычный вывод
  • --silent выбрасывает индикатор прогресса
  • --head делает HTTP-запрос HEAD, а не 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 требует для этого.)

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

печатает только код состояния для вас

Расширяя ответ, уже предоставленный Филом. Добавление параллелизма к нему не составляет никакого труда в 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-файл, который можно импортировать в любой офисный инструмент.

Это зависит от широко доступной wget, присутствует почти везде, даже на Alpine Linux.

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

Объяснения следующие:

--quiet

Отключить вывод Wget.

Источник - страницы руководства wget

--spider

[ ... ] это не загрузит страницы, только проверьте, что они там. [ ... ]

Источник - страницы руководства wget

--server-response

Напечатайте заголовки, отправленные HTTP-серверами, и ответы, отправленные FTP-серверами.

Источник - страницы руководства wget

О чем они не говорят --server-response заключается в том, что вывод этих заголовков печатается со стандартной ошибкой (sterr), поэтому необходимо перенаправить на стандартный ввод.

Вывод отправляется на стандартный ввод, мы можем передать его awk извлечь код состояния HTTP. Этот код:

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

И потому что мы хотим напечатать это... {print $2},

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

Использование curl получить только HTTP-заголовок (не весь файл) и проанализировать его:

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

wget -S -i *file* получит заголовки от каждого URL в файле.

Хотя фильтр grep для кода состояния конкретно.

Я нашел инструмент "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)

Надеюсь, это поможет!

Имея в виду, что завиток не всегда доступен (особенно в контейнерах), у этого решения есть проблемы:

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

который вернет статус выхода 0, даже если URL-адрес не существует.

В качестве альтернативы, вот разумная проверка работоспособности контейнера для использования wget:

      wget -S --spider -q -t 1 "${url}" 2>&1 | grep "200 OK" > /dev/null

Хотя он может не дать вам точного статуса, он, по крайней мере, даст вам действительные ответы о работоспособности на основе кода выхода (даже с перенаправлениями на конечной точке).

Благодаря https://mywiki.wooledge.org/BashPitfalls (вывод параллельных заданий в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 с чем-то еще, тогда это тоже может быть небезопасно.

Другие вопросы по тегам