# uname -a

# uname -a

这是关于 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 个部分组成,根据具体情况运行,这些部分不是在单遍中运行以实现简单但强大的重新连接:

  1. 即,如果存在活动连接,但没有 ping,则会断开连接。
  2. 如果没有连接,则会连接。

# 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已添加)。

相关内容