Проверка мертвых ссылок локально на статическом сайте (с помощью wget?)
Очень хороший инструмент для проверки мертвых ссылок (например, ссылок, указывающих на ошибки 404) - wget --spider
. Тем не менее, у меня есть несколько другой пример использования, когда я создаю статический веб-сайт и хочу проверить наличие неработающих ссылок перед загрузкой. Точнее, я хочу проверить оба:
-
Относительные ссылки, такие как <a href="some/file.pdf">file.pdf</a>
-
Абсолютные ссылки, скорее всего, на внешние сайты, например <a href="#" onclick="location.href='http://example.com'; return false;">example</a>
.
Я попробовал wget --spyder --force-html -i file-to-check.html
, который читает локальный файл, рассматривает его как HTML и следует за каждой ссылкой. К сожалению, он не может относиться к относительным ссылкам в локальном HTML файле (ошибки с помощью Cannot resolve incomplete link some/file.pdf
). Я попытался использовать file://
но wget
не поддерживает его.
В настоящее время у меня есть хак, основанный на запуске локального веб-сервера через python3 http.serve
и проверке локальных файлов через HTTP:
python3 -m http.server &
pid=$!
sleep .5
error=0
wget --spider -nd -nv -H -r -l 1 http://localhost:8000/index.html || error=$?
kill $pid
wait $pid
exit $error
Я не очень доволен этим по нескольким причинам:
-
Мне нужен этот sleep.5
чтобы ждать, пока веб-сервер будет готов. Без него сценарий терпит неудачу, но я не могу гарантировать, что будет достаточно 0,5 секунд. Я предпочел бы иметь способ запустить команду wget
когда сервер будет готов.
-
И наоборот, это kill $pid
кажется уродливым.
В идеале, у python3 -m http.server
будет возможность запускать команду, когда сервер будет готов, и выключится после завершения команды. Это звучит выполнимо, написав немного Python, но мне было интересно, существует ли более чистое решение.
Я что-то пропустил? Есть ли лучшее решение? Я упоминаю wget
в своем вопросе, потому что он делает почти то, что я хочу, но использование wget
не является обязательным требованием для меня (и не является python -m http.server
). Мне просто нужно что-то легко запускать и автоматизировать в Linux.
Ответы
Ответ 1
Поэтому я думаю, что вы работаете в правильном направлении. Я бы использовал wget
и python
поскольку они являются двумя доступными параметрами для многих систем. И хорошая часть состоит в том, что он выполняет работу для вас. Теперь вы хотите прослушивать Serving HTTP on 0.0.0.0
из stdout
этого процесса.
Поэтому я бы начал процесс, используя что-то вроде ниже
python3 -u -m http.server > ./myserver.log &
Обратите внимание на -u
я использовал здесь для небуферизованного вывода, это действительно важно
Теперь следующий ждет, пока этот текст появится в myserver.log
timeout 10 awk '/Serving HTTP on 0.0.0.0/{print; exit}' <(tail -f ./myserver.log)
Таким образом, 10
секунд - это ваше максимальное время ожидания здесь. И отдых не требует объяснений. Далее о вашем kill $pid
. Я не думаю, что это проблема, но если вы хотите, чтобы это было больше похоже на то, как пользователь это делает, я бы изменил ее на
kill -s SIGINT $pid
Это будет эквивалентно обработке CTRL+C
после запуска программы. Также я бы обработал скрипт SIGINT
my bash, используя что-то вроде ниже
https://unix.stackexchange.com/questions/313644/execute-command-or-function-when-sigint-or-sigterm-is-send-to-the-parent-script/313648
Вышеприведенное в основном добавляет ниже вершины сценария bash, чтобы обработать вас, убивая скрипт, используя CTRL+C
или внешний сигнал об удалении
#!/bin/bash
exit_script() {
echo "Printing something special!"
echo "Maybe executing other commands!"
trap - SIGINT SIGTERM # clear the trap
kill -- -$$ # Sends SIGTERM to child/sub processes
}
trap exit_script SIGINT SIGTERM
Ответ 2
Ответ Таруна Лалвани правильный, и, следуя приведенным советам, можно написать чистый и короткий сценарий оболочки (полагаясь на Python и awk). Другое решение - полностью написать сценарий в Python, предоставляя несколько более подробный, но, возможно, более чистый скрипт. Сервер можно запустить в потоке, затем выполняется команда проверки веб-сайта, и, наконец, сервер отключается. Нам не нужно разбирать текстовый вывод и больше не отправлять сигнал на внешний процесс. Таким образом, ключевые части сценария:
def start_server(port,
server_class=HTTPServer,
handler_class=SimpleHTTPRequestHandler):
server_address = ('', port)
httpd = server_class(server_address, handler_class)
thread = threading.Thread(target=httpd.serve_forever)
thread.start()
return httpd
def main(cmd, port):
httpd = start_server(port)
status = subprocess.call(cmd)
httpd.shutdown()
sys.exit(status)
Я написал несколько более продвинутый скрипт (с небольшим количеством синтаксического анализа командной строки поверх этого) и опубликовал его как: https://gitlab.com/moy/check-links