18

I have a couple questions about systemd. I'm having issues consistently getting my script to run once the network interface is up. I have tried Requires and After as seen below but is inconsistent with waiting for the network to be up. Am I using the right service and implementing it correctly? To by pass this right now I am running a ping check loop which is very inefficient and hackish. Any advice would be great. Thanks!

[Unit]
Description=PBU installer
Requires=network-online.service
After=network-online.service

[Service]
Type=oneshot
ExecStart=/home/pbu/current/scripts/pbu-unpack.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
1

5 Answers 5

37

I solved this problem by looking at the output of:

systemctl list-units --no-pager

That showed me many units that I didn't expect like all the network devices!

sys-devices-virtual-net-lan0.device loaded active plugged   /sys/devices/virtual/net/lan

So I added

BindsTo=sys-devices-virtual-net-lan0.device
After=sys-devices-virtual-net-lan0.device

to my unit service file and then my service didn't start until lan0 was available.

3
  • 1
    I tried using this, but it actually failed in my cloud scenario. systemctl status sys-subsystem-net-devices-ens10.device indicated that the device was considered "active" 3 seconds before the network-online.target was active. This caused the nginx startup to fail. You might be better off using network-online.target than making your unit depend on a particular network interface. Commented May 10, 2023 at 10:39
  • (Hmm, network-online.target is not necessary enough either, but hopefully the above might still be helpful in some scenarios.) Commented May 10, 2023 at 10:44
  • I ended up having to use a ExecStartPre approach in my case: serverfault.com/a/1049514/142501. Remember to do ExecStartPre= first to clear out existing pre commands, it was mandatory in my case at least. Commented May 11, 2023 at 7:40
4

This seems to be incorrect. The correct name is network-online.target. network-online.service does not exist (tested on Fedora 26).

https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/

2

Resurecting an old thread with what I hope some people might find useful. I needed to get this working with nftables on a RPi against a wireless interface that sometimes takes ages to connect. I added:

ExecStartPre=timeout 60s bash -c 'until ip a s dev wlan0; do sleep 1; done'

To the nftables.service unit to get it working. None of the other solutions here worked reliably except ExecPreStart=sleep 60 which just seemed a bit daft. The until loop terminates when the interface is up, but doesn't yet have an IP as I don't need one for my nft rules. Piping through grep '\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\/[0-9]\{1,2\}' will cause it to wait for an IPV4 address.

-1

I don't know specifically about systemd, but if you're using NetworkManager, you can use nm-online at the top of your script to wait until the network is up.

if nm-online; then 
    echo "Online"
    # do my stuff
else
    echo "Network error"
fi

By default, it'll wait 30 seconds for a network connection to become active, and return 0 (true) if it does, false otherwise.

That's at least better than pinging, I think.

2
  • Unfortunately systemd doesn't have this option. WIsh it did, would save me a lot of trouble.
    – sphchow
    Commented Jan 27, 2016 at 3:45
  • There's another catch with this method. What does it mean to be online? Just because a particular network interface is up doesn't mean that the service that I want to tie to a totally different interface can start ... Commented Jun 29, 2020 at 13:11
-1

Have you tried including Requires=network-online.target? Both my Arch and CentOS installations have this target by default. Since it's a target, it indicates that the system has reached a particular milestone in the boot process as opposed to just a single service starting. If that doesn't do it try comparing against another service unit that you know requires a network connection.

6
  • I have tried it... I'll try it again. Would i insert it as a parameter for Requires and After?
    – sphchow
    Commented Jan 27, 2016 at 3:36
  • When using "Requires", all the listed service units will start together. When using "After", systemd will make sure that all other listed units will start before yours, but will not necessarily start yours with them. One or the other should be sufficient, seems to me that both would cause a conflict.
    – smokes2345
    Commented Jan 27, 2016 at 3:41
  • I think the problem is when I use requires OR after, the service starts with or after, but I almost need the network service to finish or at least get to a certain point... or else my script will require the network before it is actually up...
    – sphchow
    Commented Jan 27, 2016 at 3:44
  • That's why I suggested using network.target. Targets indicate a particular milestone in the boot process or a group of units that work together, instead of an individual service. The idea behind using "After=network.target" is that all the units that are needed to provide network access should be activated before your unit is activated.
    – smokes2345
    Commented Jan 27, 2016 at 3:57
  • Doesn't seem to work for me. My script can't ping once the service starts. And upon looping it my ping script it does reach the ability to ping but not for a duration.
    – sphchow
    Commented Jan 27, 2016 at 18:33

You must log in to answer this question.

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