# 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

인터넷이 제대로 작동하지 않을 경우 인터넷에 다시 연결하기 위해 루트 셸에서 실행할 수 있는 스크립트를 만들었습니다. 이는 사례별로 실행되는 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

그런 다음 crontab에 설정된 대로 5분 후에 시작되는지 확인하기 위해 의도적으로 연결을 끊었습니다.

# /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

아마도 루트에 대한 첫 번째 crontab 항목이므로 cron 서비스를 다시 시작해야 할 수도 있다고 생각하여 ppp 연결을 중지하고 기다려 cron 서비스를 다시 시작하려고 시도했지만 어쨌든 다시 연결되지 않습니다. :

# /etc/rc.d/cron 다시 시작

# /etc/rc.d/ppp 중지

그런 다음 cron 로그를 확인한 결과 실제로 요청된 대로 5분마다 언급된 스크립트를 실행하려는 시도가 있음을 발견했습니다.

# tail -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기본값입니다. 이것은아니요환경이 수동으로 실행될 때처럼 보이지 않도록 하는 로그인 셸입니다. 스크립트에서 인터프리터를 명시적으로 선언하지 않고 대신 다음을 사용합니다.환경장난. 내 가설은 환경이 예상한 것과 같지 않다는 것입니다.

그런 다음 다음과 같이 수행합니다( 를 사용하여 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");

PATHcrontab 파일에서 설정할 수 있지만 거의 그렇게 하지 않습니다. 기본값은 PATH다음과 같습니다.10.2그리고최신버전( /usr/local추가됨).

관련 정보