12

I am running Debian 7 Wheezy and I need to start some screens on startup as soon as there is a fully functional internet connection. However, not, if the internet connection broke and was connected again. So only on the first functional internet connection after boot.

Could you please post a dummy script for this and tell me where to put it and make it be executed under the given conditions?

The script only needs to start the screen and then terminate but the screen should continue.


EDIT I have already heard of the /etc/network/if-up.d/ folder. But how can I make sure that the script is not executed again if the internet connection is lost and then re-established?

17

Put your script in /etc/network/if-up.d and make it executable. It will be automatically run each time a network interface comes up.

To make it do work only the first time it is run on every boot, have it check for existence of a flag file which you create after the first time. Example:

#!/bin/sh

FLAGFILE=/var/run/work-was-already-done

case "$IFACE" in
    lo)
        # The loopback interface does not count.
        # only run when some other interface comes up
        exit 0
        ;;
    *)
        ;;
esac

if [ -e $FLAGFILE ]; then
    exit 0
else
    touch $FLAGFILE
fi

: here, do the real work.
  • Will the flagfile be deletet when the server shuts down? – MinecraftShamrock Nov 6 '14 at 21:14
  • Yes, because on Debian /var/run is a volatile file system (a tmpfs). So it's guaranteed to come up empty at every fresh boot. – Celada Nov 6 '14 at 21:15
  • 1
    Good catch. I think you'd have to be really unlucky, but I think yes, because of hot-plugged interfaces that could be brought up simultaneously. So I guess you can do this atomically instead of test-then-create, which would make it safe, but what I came up with off the top of my head isn't pretty! python -c 'import os; os.open("/var/run/work-was-already-done", os.O_EXCL|os.O_CREAT, 0)' 2>/dev/null || exit 0 – Celada Nov 6 '14 at 21:25
  • 3
    @MinecraftShamrock If you use Celada's script as is, your code will run as soon as the loopback interface comes up. If you want to wait for internet connectivity, at least check that IFACE is not lo — or some virtual interface — or better, test for Internet connectivity by pinging . – Gilles Nov 7 '14 at 2:07
  • 1
    @MinecraftShamrock $IFACE can have as values any interface that comes up. You can list all of the interfaces that exist with ip link or look at which ones are configured to be brought up by scanning /etc/network/interfaces – Celada Nov 7 '14 at 14:46
8

This is a job very well suited for systemd.

Running a script as a systemd service

If your system is running systemd, then you can configure your script to run as a systemd service which provides control over the lifecycle and execution environment, as well as preconditions for starting the script, such as the network being up and running.

Create your systemd unit file under /lib/systemd/system, e.g. with vim /lib/systemd/system/autossh.service:

[Unit]
# By default 'simple' is used, see also https://www.freedesktop.org/software/systemd/man/systemd.service.html#Type=
# Type=simple|forking|oneshot|dbus|notify|idle
Description=Autossh keepalive daemon
## make sure we only start the service after network is up
Wants=network-online.target
After=network.target

[Service]
## here we can set custom environment variables
Environment=AUTOSSH_GATETIME=0
Environment=AUTOSSH_PORT=0
ExecStart=/usr/local/bin/ssh-keep-alive.sh
ExecStop=pkill -9 autossh
# don't use 'nobody' if your script needs to access user files
# (if User is not set the service will run as root)
#User=nobody

# Useful during debugging; remove it once the service is working
StandardOutput=console

[Install]
WantedBy=multi-user.target

Now you can test the service:

systemctl start autossh

Checking the status of the service:

systemctl status autossh

Stopping the service:

systemctl stop autossh

Once you verified that the service works as expected enable it with:

systemctl enable autossh

NOTE: For security purposes systemd will run the script in a restricted environment, similar to how crontab scripts are run, therefore don't make any assumptions about pre-existing system variables such as $PATH. Use the Environment keys if your script needs specific variables to be defined. Adding set -x at the top of your bash script and then running systemctl status my_service might help identify why your script is failing. As a rule of tumb, always use absolute paths for everything including echo, or explicitly define your $PATH.

2

The internet connection is brought up by an entry in /etc/rc6.d/ probably S35networking. If you change that file and insert your commands at the end, or better add a /etc/init.d/mystuff and link /etc/rc0.d/S36mystuff to it and insert your commands there, then that will start as soon as the network is up.

  • Will it be called if the connection is lost and then re-established? Because otherwise I could just put the script into /etc/network/if-up.d – MinecraftShamrock Nov 6 '14 at 21:06
  • No this is just at startup – Anthon Nov 6 '14 at 21:08
  • 1
    That will work, but just for correctness let me point out that no script in /etc/rc0.d will be run at startup, those will run at shutdown (run level 0). At startup it would be something in /etc/rc2.d or similar. Specifically for the OP's Debian wheezy, it's /etc/rcS.d/S12networking. It all symlinks to the same file, of course. Also BTW @Anthon thanks for fixing my answer: "Please" instead of "Put"? What a weird typo! – Celada Nov 6 '14 at 21:13
  • @Celada Your right it's rc6 on my (non-Debian system). I was not sure if you wanted 'Please put' there, but just "Put" seemed more crispy. BTW I upvoted your answer, it is just a better approach for networking as it has that if-up.d as generic mechanism that also works on a reconnect. – Anthon Nov 6 '14 at 21:16

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.