I have a script in /etc/network/if-up.d to connect to my VPN on startup. It appears that the script is running three times and therefore connecting to my VPN three times. After startup, looking at sudo ifconfig verifies that, in fact, three tunnels have been created. Also, I can see all three openvpn daemons when looking at the output from ps aux. How do I make sure it only runs once? And why is it running more than once? I am running Debian 7.3.

The contents of /etc/network/if-up.d/connectvpn are:

/usr/sbin/openvpn --daemon --keepalive 5 30 --config /etc/openvpn/configs/bitterroot.conf

Thank you for your help! Jeff

  • Why aren't you checking the passed arguments? Dec 31, 2013 at 22:09
  • @IgnacioVazquez-Abrams I'm sorry, I'm not sure what you mean by checking the passed arguments. Could you explain further? Thank you. Dec 31, 2013 at 22:10
  • $1, $2, etc. Dec 31, 2013 at 22:11
  • @IgnacioVazquez-Abrams There are no passed arguments to the actual script /etc/network/if-up.d/connectvpn. It just runs as-is w/o arguments. Dec 31, 2013 at 22:14

2 Answers 2


In general, ifup / ifdown does not guarantee that your script only runs once. Thus your script has to be idempotent; that is, contain its own logic not to establish a tunnel that already exists. The best way, of course, is to start the script by actually checking if the tunnel is already there:

# Exit if network device "tun0" exists.
ip link show dev tun0 >/dev/null 2>&1 && exit 0

Additionally, the scripts in if-up.d etc. run for every interface that is brought up. As Jeff correctly observes, the if-*.d scripts receive no arguments specifying e.g. which interface is coming up.

Instead, per the interfaces(5) man page:

   There  exists  for  each  of  the  above  mentioned options a directory
   /etc/network/if-<option>.d/ [...]

   All of these commands have access to the  following  environment  vari‐

   IFACE  physical name of the interface being processed

          logical name of the interface being processed

  [... and more ...]

The solution is to start the script with a check for the correct IFACE value, e.g.:

# Exit if we're not starting "eth0".
[ "$IFACE" = 'eth0' ] || exit 0

Otherwise, the script will run for every network device, including lo, at which point it may be too early to establish a tunnel.



if [ "$MODE" != start ]; then
        exit 0

to your script.

In general, to debug things like this it's customary to first make your script consist only of something like

echo "$@" >/tmp/blah
set >>/tmp/blah

and inspect the contents of /tmp/blah after the script is run to get the rough idea of what arguments the script is passed (if any) and what it sees in its environment when runs.

  • Thank you, @kostix. This worked for debugging, unfortunately for me it appears this was not the problem I was having... Jan 22, 2014 at 13:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .