This is regarding the FreeBSD:

# uname -a

FreeBSD gw-mail 10.2-RELEASE FreeBSD 10.2-RELEASE #0 r286666: Wed Aug 12 19:31:38 UTC 2015     root@releng1.nyi.freebsd.org:/usr/obj/usr/src/sys/GENERIC  i386

I've created a script, that works from the root shell to reconnect an internet connection, if it's not working. It consists of 2 parts, that run, depending on the situation, which are not ran in the single pass for simple, but robust reconnection:

  1. I.e., if there is an active connection, but no ping, it disconnects.
  2. If there is no connection, it connects.

# 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
    my %ppp = (
            status=>system("/etc/rc.d/ppp status")
    print "PPP(status): $ppp{status}\n";
    if($tun == 0){
            $ping = system("ping -c4");
            print "PING: $ping\n";
            if($ping != 0){
                    tailEcho("CONNECTED, but NO PING => Disconnecting", $file);
                            $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);
                    print "ALREADY CONNECTED!!!\n";
    if($tun != 0){
            if($ping != 0){
                    tailEcho("NO CONNECTION => Reconnecting", $file);
                            $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");
                            print "PING: $ping\n";
                    }until($ppp{status} == 0);
    sub tailEcho{
            my ($str, $file) = @_;
            if(open(my $L, ">>$file")){
                    print $L time.":\t$str\n";

I added it to root job list:

# crontab -e

*/5 * * * * /root/bin/ars-reconnect.pl

Then, I porpusefully disconnected the connection to check, if if will come up in 5 minutes, as set in crontab:

# /etc/rc.d/ppp stop

After a wait, the connection is not reconnected and the '/var/log/ars.log' (as in the script) log doesn't have a new reconnection entry.

If I just run it manually:

# /root/bin/ars-reconnect.pl

It reconnects and the '/var/log/ars.log' gets a new reconnection line written:

# # tail /var/log/ars.log
1630330022:     NO CONNECTION => Reconnecting

I thought, that maybe the cron service needs to be restarted, since it was the 1st crontab entry for the root, so i tried to restart the cron service by, stop the ppp connection and wait, but it doesn't reconnect anyway.:

# /etc/rc.d/cron restart

# /etc/rc.d/ppp stop

Then I checked the cron log and found, that there was actually attempts to execute the mentioned script for every 5 minutes, as required:

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

But why then it doesn't work. I.e., why doesn't it reconnect, when on execution by cron?

I have a feeling, that it could be because of some permission issue, but how can I find it out, since cron log doesn't throw any error message.


My guess is that the environment does not look as you'd expect. Cron runs jobs in a near empty environment. It is then a very good habit to use full qualified paths. I furthermore prefer to explicitly state the interpreter of any script as well. To such a degree that I would normally start any .sh script using /bin/sh -c /mypath/myscript.sh (when using crontab!)

What happens is that the crontab entry is executed with the SHELL set by crontab (see crontab(5)). This is /bin/sh as default. It is not a login shell so the environment does not look like when you run it manually. You do not explicitly state the interpreter in your script but use the env trick. My assumption here is that the environment does not look like expected.

I would then do something like this (with crontab -e):

*/5 * * * * /usr/bin/perl /root/bin/ars-reconnect.pl

For extra debug info I would output everything to a file:

*/5 * * * * /usr/bin/perl /root/bin/ars-reconnect.pl >/root/crondebug.output 2>&1

The output of the cronjob would normally be mailed to you but the above might be easier with one less moving part.

This means that you should probably update your script too:

$ping = system("/sbin/ping -c4");

You can set PATH in the crontab file but I personally rarely do this. Notice that the default PATH is different between 10.2 and newer versions (/usr/local has been added).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.