# rc.d script start at boot (not running in background)



## da1 (Jul 12, 2010)

Hello fellas,

My system: FreeBSD-8.0 with nothing special (fresh install of base + kernel) <- vmware test box.

After reading I came up with the following script (pls ignore the grammar mistakes - they were made with intent):


```
#!/bin/sh
#
# PROVIDE: connection_check
# REQUIRE: networking
# BEFORE:  LOGIN
# KEYWORD: nojail shutdown
#
#
# Connection_check_enable (bool)        Set to "NO" by default.
#                                       Set it to "YES" in "/etc/rc.conf" to enable it on boot.

. /etc/rc.subr

name="connection_check"
start_cmd="${name}_start"
rcvar=`set_rcvar`
pidfile="/var/run/$name.pid"

: ${connection_check_enable="NO"}

load_rc_config $name

connection_check_start()
{
cd /tmp
x=5
while [ $x -gt 1 ]
do
fetch -q http://google.com
if [ -f /tmp/google.com ];then
echo "`date` All is ok. Internet connection is up. Sleeping for 5 min..." >> /var/log/messages
else
echo "`date` We have no internet. Commencing pppoe restart procedure" >> /var/log/messages
/etc/rc.d/ppp stop >> /var/log/messages
wait
ifconfig tun0 destroy >> /var/log/messages
wait
ifconfig tun1 destroy >> /var/log/messages
wait
/etc/rc.d/ppp start >> /var/log/messages
wait
fi

rm -f /tmp/google.com
sleep 300
done
}

run_rc_command "$1"
```

As you can see, the script is very simple and kiddie style

My problem: when I launch the script with [cmd=]/etc/rc.d/connexion_check start[/cmd] it does not go into background, hence causing the boot process to halt when reaching the script. If I run the script outside the rc.d framework, I simply append a "&" sign at the end and the problem goes away. 

Here on the other hand, it is a completely different story. I've been poking my eyes out for ~2 days trying to figure it out but with no luck.

Any advice is highly welcomed.


----------



## wblock@ (Jul 12, 2010)

Trying to do that in one piece is the problem.  The /etc/rc.d scripts are expected to run and exit.

First, try the easiest way: start PPP with the "ddial" mode and it should reconnect automatically.  See /etc/defaults/rc.conf.

But if that doesn't do it, I'd suggest starting the reconnect script from crontab(5) with the @reboot time.  cron could also run it every five minutes, so the script doesn't need to sleep or run in the background at all.  Simpler is better.

There are other optimizations that could be done, but hopefully the ddial mode will fix it.


----------



## da1 (Jul 12, 2010)

> Trying to do that in one piece is the problem. The /etc/rc.d scripts are expected to run and exit.



In that case, is there a way to just start the script at boot ? without using rc.d ? 
problem is that I was unable to start it at boot. in a solaris machine, you put the script in the proper run level folder and it starts. since BSD has no run-levels  ... welcome headache  



> First, try the easiest way: start PPP with the "ddial" mode and it should reconnect automatically. See /etc/defaults/rc.conf.


PPP is started with "ddial" at boot by "ppp_enable="YES" and "ppp_mode="ddial"". The problem I am having with my ISP is that every once in a while, I get no connexion to the outside world. However, the interface is up, IP is assigned and the connexion does not disconnect, therefore there is nothing to reconnect (this usually happens when my ISP want's to renew my IP - not all the times - but some times). the PPP daemon does not check for connectivity after a successful start. This is where the script kicks in.



> But if that doesn't do it, I'd suggest starting the reconnect script from crontab(5) with the @reboot time. cron could also run it every five minutes, so the script doesn't need to sleep or run in the background at all. Simpler is better.



Before posting, I was thinking about crontab and how I could make the magic happen. I agree, "simpler is better". I will give it a shot.


Thx for your answer and your time. I will post back as soon as I have some news.


----------



## gordon@ (Jul 13, 2010)

I can think of one script, /etc/rc.d/bgfsck, that sleeps in the background after being invoked by the rc.d system. Take a look at that one and see if you can do something similar. It appears to use a subshell to do its work.

Alternatively, you could code up the script and put it into /etc/rc.local invoked in the background.


----------



## mickey (Jul 13, 2010)

da1 said:
			
		

> The problem I am having with my ISP is that every once in a while, I get no connexion to the outside world. However, the interface is up, IP is assigned and the connexion does not disconnect, therefore there is nothing to reconnect (this usually happens when my ISP want's to renew my IP - not all the times - but some times). the PPP daemon does not check for connectivity after a successful start.



You could try, whether enabling the *lqr* or *echo* options in your /etc/ppp/ppp.conf helps resolving this issue. i.e.:

```
enable lqr
enable echo
```
These options periodically send test packets to the remote PPP, and if more than 5 go unanswered, the connection is considered broken. See ppp(8) for details.

If that doesn't help either, you can create the files /etc/ppp/ppp.linkup and /etc/ppp/ppp.linkdown. These files have the same format as the ppp.conf file, and are executed each time the link comes up/goes down respectively. You can then use these to start/terminate your connection check script. This way it is also possible to pass parameters to your script, like local/remote IP-address, interface name, DNS server addresses, etc...

i.e.:
/etc/ppp/ppp.linkup:

```
MYADDR:
        set proctitle INTERFACE:MYADDR->HISADDR
        !bg /etc/ppp/check-connection.sh INTERFACE MYADDR HISADDR DNS0 DNS1
```
/etc/ppp/ppp.linkdown:

```
MYADDR:
        set proctitle link-down
        shell pkill -f check-connection.sh
```

From within your connection check script, you may then use `$ pppctl close` to close/reopen the PPP connection, if it has become unresponsive.


----------



## da1 (Jul 13, 2010)

hello fellas,

thx a lot for all your help and opinions. for the moment I have adjusted the script to:


```
#!/bin/sh


cd /tmp
fetch -q http://google.com
if [ ! -f /tmp/google.com ];then
echo "`date` We have no internet. Commencing pppoe restart procedure" >> /var/log/messages
/etc/rc.d/ppp stop >> /var/log/messages
wait
ifconfig tun0 destroy >> /var/log/messages
wait
ifconfig tun1 destroy >> /var/log/messages
wait
/etc/rc.d/ppp start >> /var/log/messages
wait
fi

rm -f /tmp/google.com
```

and I have schedules it via crontab every 5 minutes as:


```
*/5     *       *       *       *       root    /root/scripts/connection_check
```

I will try playing with those other ppp options and also I will try to "code" the script in another way (to see the differences and to learn).

Again, thx a lot


----------



## wblock@ (Jul 13, 2010)

The lqr/echo options mentioned by mickey above are really nice, and appear to be the most elegant way of doing this.  Just wanted to make a few comments on the script:


```
#!/bin/sh
cd /tmp
fetch -q http://google.com
```

1. It's important to use full paths in scripts to be called from cron (and often otherwise).  You can improve readability by assigning them to variables:

```
fetch="/usr/bin/fetch"
$fetch ...
```

2. Fetching a whole web page, even a small one, is overkill to test a link.  How about a ping, or ntpdate, or something not so big.
3. Fetch/ping/whatever your ISP.  Additional load on the net is not needed beyond your ISP to test that local link.


```
if [ ! -f /tmp/google.com ];then
echo "`date` We have no internet. Commencing pppoe restart procedure" >> /var/log/messages
/etc/rc.d/ppp stop >> /var/log/messages
wait
ifconfig tun0 destroy >> /var/log/messages
wait
ifconfig tun1 destroy >> /var/log/messages
wait
/etc/rc.d/ppp start >> /var/log/messages
wait
fi

rm -f /tmp/google.com
```

4. Spaces are free.  Indenting code appropriately makes it much easier on you and others.


----------



## mickey (Jul 13, 2010)

The lqr/echo options are nice, but I guess whether they can help in this specific case, depends upon where the problem is located, as they both happen at LCP level. So if the problem is at some higher level, they might not be able to detect it.

On a sidenote: Calling /etc/rc.d/ppp to stop and then start ppp is overkill.
`$ pppctl close` does exactly what you want without killing off the ppp process. Additionally _pppctl_ comes with an interactive command mode, when called without arguments. So you can test things interactively before scripting it down.

Just curious: why are you calling ifconfig to destroy _tun0_ and _tun1_ ?


----------



## da1 (Jul 13, 2010)

*@wblock:*


```
#!/bin/sh

file="/var/log/messages"
cd /tmp
/usr/bin/fetch -q http://google.com
if [ ! -f /tmp/google.com ];then
        echo "`date` We have no internet. Commencing pppoe restart procedure" >> $file
        /etc/rc.d/ppp stop >> $file
                wait
        ifconfig tun0 destroy >> $file
                wait
        ifconfig tun1 destroy >> $file
                wait
        /etc/rc.d/ppp start >> $file
                wait
fi

rm -f /tmp/google.com
```

adjusted. what else,in your opinion, should I improve on this one ?



> 2. Fetching a whole web page, even a small one, is overkill to test a link. How about a ping, or ntpdate, or something not so big.


Initially, ping was the way I wanted to go but since I failed (miserably) in creating something that works, I had to do it another way. If you can suggest me the way to do it, by all means, pls do so.



> 3. Fetch/ping/whatever your ISP. Additional load on the net is not needed beyond your ISP to test that local link.


I thought about that and the thought went away when I saw that on occasions I can browse the local LAN in my area/city but with no external access (nice ISP, eh ?)



> 4. Spaces are free. Indenting code appropriately makes it much easier on you and others.


Indeed, indent helps. I'm just did not get the idea of it. I mean, the "standard" way of indenting. I just do it according to my "feeling" (to say so).

*@mickey:*


> The lqr/echo options are nice, but I guess whether they can help in this specific case, depends upon where the problem is located, as they both happen at LCP level. So if the problem is at some higher level, they might not be able to detect it.


My thought exactly. Of course, I can give them a shot (they were set in ppp.conf). If they actually work, I will see no logs about restarted ppp.



> On a sidenote: Calling /etc/rc.d/ppp to stop and then start ppp is overkill.
> $ pppctl close
> does exactly what you want without killing off the ppp process. Additionally pppctl comes with an interactive command mode, when called without arguments. So you can test things interactively before scripting it down.


I am reading about pppctl now and I will try it out as soon as I have some time.



> Just curious: why are you calling ifconfig to destroy tun0 and tun1 ?


because sometimes, the interface remains up even after I do "/etc/rc.d/ppp stop".

The thing is that this box is 3 countries away from me and the owner of it has limited unix/linux skills. Therefore, I prefer writing a couple of extra lines of script just to be on the safeside


----------



## mickey (Jul 13, 2010)

da1 said:
			
		

> Initially, ping was the way I wanted to go but since I failed (miserably) in creating something that works, I had to do it another way. If you can suggest me the way to do it, by all means, pls do so.



Try something like this, preferably with the ppp.linkup/down scripts suggested above:

```
#! /bin/sh

testhost="www.google.com"
timeout=5
interval=300

while /sbin/ping -q -n -c 1 -W $timeout $testhost 2>&1 > /dev/null; do
        sleep $interval
done

echo "Your link is borken"

/usr/sbin/pppctl close

exit 0
```



			
				da1 said:
			
		

> My thought exactly. Of course, I can give them a shot (they were set in ppp.conf). If they actually work, I will see no logs about restarted ppp.


Enabling them shouldn't hurt. lqr must be negotiated upon, so there is a chance your ISP's PPP says "Nope, I wont". Echo should work in any case.



			
				da1 said:
			
		

> because sometimes, the interface remains up even after I do "/etc/rc.d/ppp stop".


Shouldn't happen when using pppctl.


----------



## wblock@ (Jul 14, 2010)

da1 said:
			
		

> ```
> #!/bin/sh
> 
> file="/var/log/messages"
> ...



I generally use two-space indenting for sh.  Only indent where the control changes, so the "wait" statements would be at the same level as the ifconfig statements.  And use variables to define the commands and values:


```
#!/bin/sh

testhost="google.com"
logfile="/var/log/messages"

date="/bin/date"
ifconfig="/sbin/ifconfig"
ping="/sbin/ping"
ppp="/etc/rc.d.ppp"

$ping -c2 $testhost > /dev/null
if [ $? -ne 0 ];then
  echo "`$date` We have no internet. Commencing pppoe restart procedure" >> $logfile
  $ppp stop >> $logfile
  $ifconfig tun0 destroy >> $logfile
  $ifconfig tun1 destroy >> $logfile
  $ppp start >> $logfile
fi
```

Untested, but I think it's pretty close.  And I can't speak for the method of restarting PPP.  Pretty sure the waits are unnecessary, so out they go.

The ping tries twice to be sure, with the output discarded because we only care about the return value in $?.


----------



## da1 (Jul 14, 2010)

> Pretty sure the waits are unnecessary, so out they go.


I use "wait" because I am a bit unsure of the way the script launches the cmd's I put inside. In this case I have 4 (stop,destroy,destroy and start). I don't know if they are executed one after the other one, without waiting for the previous to finish (ex: if "stop" takes 2 min, do the other ones start or wait for 2 min for "stop" to finish ?) or if they are executed similar to (from a shell): cmd1 && cmd2 && cmd3 && cmd4 (in this example, the second one does not start until the first one finishes .. and so on). "wait", in this case, is my way of walking on the safe side.

I have successfully used your script wblock and replaced the old, initial, one.


@mickey: no time to read pppctl and play with it yet.


----------



## wblock@ (Jul 15, 2010)

da1 said:
			
		

> I use "wait" because I am a bit unsure of the way the script launches the cmd's I put inside. In this case I have 4 (stop,destroy,destroy and start). I don't know if they are executed one after the other one, without waiting for the previous to finish



Nope, they're synchronous, unless the program runs in the background by itself, or you run it that way.  For example:


```
#!/bin/sh
  echo "starting"
  sleep 5
  echo "done"
```

Takes about five seconds to run.  Now add an "&" so the sleep command runs in the background:


```
#!/bin/sh
  echo "starting"
  sleep 5 &
  echo "done"
```

That comes back nearly instantly, because it didn't have to wait for sleep to finish.

ifconfig doesn't background itself.  The ppp commands are running through /etc/rc.d, which could do something weird with them.
Probably the right way is to use /usr/bin/ppp directly, so you know what options are being given to it.  You can run shell scripts with -x to see exactly what they do, like:
`# sh -x /etc/rc.d/ppp stop`


----------



## da1 (Jul 15, 2010)

I used "set -x" and "set -v" in the script last night and I did not see anything weird. It worked like I expected it to work.

TODO: read/understand/play with pppctl


----------

