这是关于 FreeBSD 的:
# uname -a
FreeBSD gw-mail 10.2-RELEASE FreeBSD 10.2-RELEASE #0 r286666: Wed Aug 12 19:31:38 UTC 2015 [email protected]:/usr/obj/usr/src/sys/GENERIC i386
我创建了一个脚本,该脚本可以从根 shell 运行,以在无法正常工作时重新连接互联网连接。它由 2 个部分组成,根据具体情况运行,这些部分不是在单遍中运行以实现简单但强大的重新连接:
- 即,如果存在活动连接,但没有 ping,则会断开连接。
- 如果没有连接,则会连接。
# vi /root/bin/ars-reconnect.pl
#!/usr/bin/env perl
my $file = '/var/log/ars.log';
my $tun = system("ifconfig tun0");
print "TUN: $tun\n";
my $ping = 1;
#/etc/rc.d/ppp status ; /etc/rc.d/ppp stop ; ifconfig ; sleep 5 ; /etc/rc.d/ppp status ; sleep 5 ; /etc/rc.d/ppp stop ; sleep 5 ; /etc/rc.d/ppp stop ; sleep 5 ; /etc/rc.d/ppp start ; sleep 5 ; ifconfig ; /etc/rc.d/ppp status ; ping -c 2 8.8.8.8
my %ppp = (
status=>system("/etc/rc.d/ppp status")
);
print "PPP(status): $ppp{status}\n";
if($tun == 0){
$ping = system("ping -c4 8.8.8.8");
print "PING: $ping\n";
if($ping != 0){
tailEcho("CONNECTED, but NO PING => Disconnecting", $file);
do{
$ppp{stop} = system("/etc/rc.d/ppp stop");
print "PPP(stop): $ppp{stop}\n";
$ppp{status} = system("/etc/rc.d/ppp status");
print "PPP(status): $ppp{status}\n";
}until($ppp{status} != 0);
}else{
print "ALREADY CONNECTED!!!\n";
}
}
if($tun != 0){
if($ping != 0){
tailEcho("NO CONNECTION => Reconnecting", $file);
do{
$ppp{start} = system("/etc/rc.d/ppp start");
print "PPP(start): $ppp{start}\n";
$ppp{status} = system("/etc/rc.d/ppp status");
print "PPP(status): $ppp{status}\n";
$ping = system("ping -c4 8.8.8.8");
print "PING: $ping\n";
}until($ppp{status} == 0);
}
}
sub tailEcho{
my ($str, $file) = @_;
if(open(my $L, ">>$file")){
print $L time.":\t$str\n";
close($L);
}
}
我将其添加到根作业列表中:
# crontab -e
*/5 * * * * /root/bin/ars-reconnect.pl
然后,我故意断开连接来检查它是否会在 5 分钟后启动,如 crontab 中设置的那样:
# /etc/rc.d/ppp 停止
等待后,连接不会重新连接,并且“/var/log/ars.log”(如脚本中所示)日志没有新的重新连接条目。
如果我只是手动运行它:
# /root/bin/ars-reconnect.pl
它重新连接,'/var/log/ars.log' 写入新的重新连接行:
# # tail /var/log/ars.log
1630330022: NO CONNECTION => Reconnecting
我想,也许 cron 服务需要重新启动,因为它是 root 的第一个 crontab 条目,所以我尝试通过停止 ppp 连接并等待来重新启动 cron 服务,但它无论如何都不会重新连接。:
# /etc/rc.d/cron 重新启动
# /etc/rc.d/ppp 停止
然后我检查了 cron 日志,发现实际上有按要求每 5 分钟尝试执行一次提到的脚本:
# 尾部 -n 20 /var/log/cron
Aug 30 14:15:00 gw-mail /usr/sbin/cron[15208]: (root) CMD (/root/bin/ars-reconnect.pl)
Aug 30 14:20:00 gw-mail /usr/sbin/cron[15212]: (root) CMD (/usr/libexec/atrun)
Aug 30 14:20:00 gw-mail /usr/sbin/cron[15213]: (root) CMD (/root/bin/ars-reconnect.pl)
Aug 30 14:22:00 gw-mail /usr/sbin/cron[15216]: (operator) CMD (/usr/libexec/save-entropy)
Aug 30 14:25:00 gw-mail /usr/sbin/cron[15229]: (root) CMD (/usr/libexec/atrun)
Aug 30 14:25:00 gw-mail /usr/sbin/cron[15230]: (root) CMD (/root/bin/ars-reconnect.pl)
Aug 30 14:30:00 gw-mail /usr/sbin/cron[15234]: (root) CMD (/usr/libexec/atrun)
Aug 30 14:30:00 gw-mail /usr/sbin/cron[15235]: (root) CMD (/root/bin/ars-reconnect.pl)
Aug 30 14:33:00 gw-mail /usr/sbin/cron[15239]: (operator) CMD (/usr/libexec/save-entropy)
Aug 30 14:35:00 gw-mail /usr/sbin/cron[15252]: (root) CMD (/usr/libexec/atrun)
Aug 30 14:35:00 gw-mail /usr/sbin/cron[15253]: (root) CMD (/root/bin/ars-reconnect.pl)
Aug 30 14:36:25 gw-mail crontab[15255]: (root) BEGIN EDIT (root)
Aug 30 14:37:04 gw-mail crontab[15255]: (root) END EDIT (root)
Aug 30 14:40:00 gw-mail /usr/sbin/cron[15259]: (root) CMD (/usr/libexec/atrun)
Aug 30 14:40:00 gw-mail /usr/sbin/cron[15260]: (root) CMD (/root/bin/ars-reconnect.pl)
Aug 30 14:44:00 gw-mail /usr/sbin/cron[15264]: (operator) CMD (/usr/libexec/save-entropy)
Aug 30 14:45:00 gw-mail /usr/sbin/cron[15278]: (root) CMD (/usr/libexec/atrun)
Aug 30 14:45:00 gw-mail /usr/sbin/cron[15279]: (root) CMD (/root/bin/ars-reconnect.pl)
Aug 30 14:50:00 gw-mail /usr/sbin/cron[15285]: (root) CMD (/usr/libexec/atrun)
Aug 30 14:50:00 gw-mail /usr/sbin/cron[15286]: (root) CMD (/root/bin/ars-reconnect.pl)
但为什么它不起作用。即,当由 cron 执行时,为什么它不重新连接?
我有一种感觉,这可能是因为某些权限问题,但我怎样才能找到它,因为 cron 日志不会抛出任何错误消息。
答案1
我的猜测是环境并不像你想象的那样。 Cron 在几乎空的环境中运行作业。因此,使用完全限定路径是一个非常好的习惯。此外,我还更喜欢明确说明任何脚本的解释器。达到这样的程度,我通常会使用(当使用 crontab 时!)启动任何.sh
脚本/bin/sh -c /mypath/myscript.sh
发生的情况是该crontab
条目按照 crontab 设置执行SHELL
(参见定时任务(5))。这是/bin/sh
默认的。这是不是一个登录 shell,因此环境看起来不像手动运行它时那样。您没有在脚本中明确声明解释器,而是使用环境诡计。我的假设是环境看起来不像预期的那样。
然后我会做这样的事情(用crontab -e
):
*/5 * * * * /usr/bin/perl /root/bin/ars-reconnect.pl
对于额外的调试信息,我会将所有内容输出到文件中:
*/5 * * * * /usr/bin/perl /root/bin/ars-reconnect.pl >/root/crondebug.output 2>&1
cronjob 的输出通常会邮寄给您,但由于少了一个移动部件,上述操作可能会更容易。
这意味着您也应该更新您的脚本:
$ping = system("/sbin/ping -c4 8.8.8.8");
PATH
你可以在crontab文件中设置,但我个人很少这样做。请注意,默认值PATH
之间有所不同10.2和较新的版本(/usr/local
已添加)。