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

87

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

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

ИЗМЕНИТЬ Обратите внимание, что возникает проблема, если на странице отображается сообщение «404 not found», но возвращается сообщение 200 OK. Это неправильно настроенный веб-сервер, но вам, возможно, придется рассмотреть этот случай.

Для получения дополнительной информации см. Проверка, ведет ли URL-адрес на страницу, содержащую текст «404».

Ману
источник
2
Честно говоря, «ошибка» моего скрипта возникает только тогда, когда сервер возвращает HTTP-код 200, но в основном тексте написано «404 not found», что является некорректным поведением веб-сервера.
Фил
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 делает 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.)

Фил
источник
Очень хорошо. Могу ли я выполнить эту команду для каждого URL в моем файле?
Ману
1
@Manu: Да, я отредактировал свой ответ, чтобы показать один из возможных способов завершения команды curl. Предполагается, что url-list.txt содержит по одному URL на строку.
Фил
1
Я не знаю, почему скрипт сверху andswer всегда дает мне 000 на выходе, но когда я запускаю команду только один раз без цикла, она работает ...
Кароль Ф,
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}'

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

user551168
источник
9
+1 Показывает несколько кодов при перенаправлении URL-адреса, каждый с новой строки.
Ashfame
Пришлось избавиться от --spider, чтобы он работал с запросом, который я пытался сделать, но работает.
amitavk 06
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 процессов curl активными в любое время (т.е. 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, который можно импортировать в любой офисный инструмент.

Estani
источник
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

--spider

[...] он не будет загружать страницы, просто проверьте, что они есть. [...]

Источник - справочные страницы wget

--server-response

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

Источник - справочные страницы wget

О чем они не говорят, так это о --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}'
Salathiel Genèse
источник
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чем-то другим, это тоже может быть небезопасно.

Оле Танге
источник