在静态网站中本地检查死链接(使用 wget?)
Checking for dead links locally in a static website (using wget?)
一个非常好的检查死链接(例如指向 404 错误的链接)的工具是 wget --spider
。但是,我有一个稍微不同的用例,我生成一个静态网站,并想在上传之前检查是否有损坏的链接。更准确地说,我想检查两者:
相关链接如<a href="some/file.pdf">file.pdf</a>
绝对链接,最有可能指向 <a href="http://example.com">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.
上实现自动化
所以我认为您 运行 的方向是正确的。我会使用 wget
和 python
,因为它们是许多系统上两个现成的选项。好的部分是它可以为您完成工作。现在您想要的是从该进程的 stdout
中监听 Serving HTTP on 0.0.0.0
。
所以我会使用下面的方法开始这个过程
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
秒是您在这里的最长等待时间。剩下的是self-explanatory。接下来是关于你的 kill $pid
。我认为这不是问题,但如果您希望它更像用户的操作方式,那么我会将其更改为
kill -s SIGINT $pid
这相当于您在启动程序后处理 CTRL+C
。我也会使用下面的东西处理 SIGINT
我的 bash 脚本
上面基本上在 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
Tarun Lalwani 的回答是正确的,按照那里给出的建议,可以编写一个干净而简短的 shell 脚本(依赖于 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)
我写了一个稍微更高级的脚本(在此之上有一些 command-line 选项解析)并将其发布为:https://gitlab.com/moy/check-links
一个非常好的检查死链接(例如指向 404 错误的链接)的工具是 wget --spider
。但是,我有一个稍微不同的用例,我生成一个静态网站,并想在上传之前检查是否有损坏的链接。更准确地说,我想检查两者:
相关链接如
<a href="some/file.pdf">file.pdf</a>
绝对链接,最有可能指向
<a href="http://example.com">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.
所以我认为您 运行 的方向是正确的。我会使用 wget
和 python
,因为它们是许多系统上两个现成的选项。好的部分是它可以为您完成工作。现在您想要的是从该进程的 stdout
中监听 Serving HTTP on 0.0.0.0
。
所以我会使用下面的方法开始这个过程
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
秒是您在这里的最长等待时间。剩下的是self-explanatory。接下来是关于你的 kill $pid
。我认为这不是问题,但如果您希望它更像用户的操作方式,那么我会将其更改为
kill -s SIGINT $pid
这相当于您在启动程序后处理 CTRL+C
。我也会使用下面的东西处理 SIGINT
我的 bash 脚本
上面基本上在 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
Tarun Lalwani 的回答是正确的,按照那里给出的建议,可以编写一个干净而简短的 shell 脚本(依赖于 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)
我写了一个稍微更高级的脚本(在此之上有一些 command-line 选项解析)并将其发布为:https://gitlab.com/moy/check-links