外部路由器很麻烦。有时它们会挂起,必须手动关闭并重新打开才能重新激活连接。服务器做不了什么。但是,当它检测到卡断开连接时,它可以发出警报,或者可以更改路由,或者,如果不使用外部路由器,它甚至可以自行恢复连接。
我有两个 ISP,还有一个 cron 任务,它会不时检查两个连接。其核心部分的代码如下:
/usr/bin/traceroute -4 -n -m 8 -i $isp1_if -s $isp1_ip $isp1_tracehost \
> $output 2>&1 || {
logger -s -t "$0" -p daemon.crit "ISP1 unreachable on $isp1_if"
# Code to restart pppd omitted
}
/usr/sbin/traceroute -4 -n -m 4 -i $isp2_if -s $isp2_ip $isp2_tracehost \
> $output 2>&1 ||
logger -s -t "$0" -p daemon.crit "ISP2 unreachable on $isp2_if"
这些变量为每个 ISP 提供了接口(_if
)、地址(_ip
)和一个不远的要跟踪的主机(_tracehost
)。 $output
是一个变量,因为脚本可以通过 cron 静默运行,也可以在手动运行时详细运行(如下所示)。
对于 ISP1,没有外部路由器。有一个由服务器直接管理的 PPP 连接。如果发生故障,通常会在第一次尝试时恢复连接。
对于 ISP2(带有外部路由器),我满足于发出警报。但是,它不起作用。例如,当外部路由器挂起时,我得到:
traceroute to 94.198.103.150 (94.198.103.150), 8 hops max, 60 byte packets
1 100.99.0.119 2.755 ms 2.781 ms 2.885 ms
2 * * *
3 62.149.185.219 4.780 ms 4.742 ms 4.738 ms
4 62.149.185.206 4.697 ms 4.854 ms 4.916 ms
5 185.1.114.77 5.045 ms 5.254 ms 5.534 ms
6 94.198.103.150 4.653 ms 4.334 ms 4.404 ms
traceroute to 185.204.135.186 (185.204.135.186), 4 hops max, 60 byte packets
1 * * *
2 * * *
3 * * *
4 * * *
尽管没有到达主机,但 traceroute 返回了退出代码 0,因此没有发出警报。
重启路由器之后,输出变成:
traceroute to 94.198.103.150 (94.198.103.150), 8 hops max, 60 byte packets
1 100.99.0.119 2.862 ms 2.827 ms 2.815 ms
2 * * *
3 62.149.185.221 6.841 ms 62.149.185.219 11.377 ms 62.149.185.221 6.763 ms
4 62.149.185.206 4.767 ms 4.888 ms 4.851 ms
5 185.1.114.77 4.885 ms 4.986 ms 5.050 ms
6 94.198.103.150 4.527 ms 4.467 ms 4.486 ms
traceroute to 185.204.135.186 (185.204.135.186), 4 hops max, 60 byte packets
1 192.168.1.1 0.302 ms !N 0.341 ms !N *
我猜想在第一种情况下,traceroute 可能会失败,因为isp1_if=ppp0
当它挂起时,它找不到接口。在第二种情况下isp2_if=eth1
,它会愉快地将数据包发送到任何地方。
我如何修复我的脚本以便它能够检测停机时间eth1
?
答案1
我排除了,ping
因为不必依赖特定的目标主机。到达任何东西就足够了。
最简单的解决方案是计算输出的行数。如果没有得到任何结果,traceroute
则尝试 100max_ttl
次(默认为 30 次)。由于选择的目标主机较近,因此输出的行数必须低于此值。
ISP2 的代码更改如下:
max_ttl=5
outfile=$(mktemp)
/usr/sbin/traceroute -4 -n -m $max_ttl -i $isp2_if -s $isp2_ip $isp2_tracehost 2>&1 \
| tee $outfile > $output && (( $(wc -l < $outfile) < $max_ttl )) ||
logger -s -t "$0" -p daemon.crit "ISP2 unreachable on $isp2_if"
rm $outfile
请注意,输出还包含标题行。
我习惯在通过 调用时或使用适当的选项从命令行调用时tee
继续使用。output
/dev/null
cron
/dev/fd/1