33

I'm trying to create a systemd service on Debian Jessie. I need it to start after network-online.target is reached.

The problem is network-online.target fires at the same time as network.target and at that time my interfaces are not configured yet, just started DHCP query.

It looks like this issue is specific to Debian because it uses legacy network configuration.

How to bypass this problem or how to make network-online.target working?

5
  • What's the output of systemctl list-dependencies network-online.target? Also, note that the network-online.target may not necessary mean that there is Internet access. See this page for more info. Jul 22, 2015 at 23:10
  • Output of the command is: network-online.target ● └─systemd-networkd-wait-online.service I've read that page already, I understand the basic concept there, but still it is very strange to have no defined point where network critical services can start. At least it could wait for proper DHCP assign.
    – 10robinho
    Jul 22, 2015 at 23:42
  • This means that the network-online.target depends only on the systemd-networkd-wait-online.service saying that it is ready. It doesn't depend on NetworkManager saying it's ready, nor check that ifup brought all links up successfully (if you use that method to configure your network). Ubuntu, on the other hand, depends on ifup and NetworkManager, but not for systemd-networkd-wait-online.. Jul 23, 2015 at 0:12
  • How are you configuring your network: /etc/network/interfaces, systemd .network files, or NetworkManager? Jul 23, 2015 at 0:18
  • 1
    Your are right, network-online.target and network.target are triggered right after ifup. I use debian default, so /etc/network/interfaces with dhcp address. It looks like networkd could be better solution, but it's not straightforward to implement.
    – 10robinho
    Jul 23, 2015 at 0:24

6 Answers 6

24
+150

Since you're using /etc/network/interfaces, you'll need a systemd service to monitor the status of each interface. Check to see if you have /lib/systemd/system/ifup-wait-all-auto.service (installed by the ifupdown package in Ubuntu 15.04). If not, then create /etc/systemd/system/ifup-wait-all-auto.service, and paste in the following:

[Unit]
Description=Wait for all "auto" /etc/network/interfaces to be up for network-online.target
Documentation=man:interfaces(5) man:ifup(8)
DefaultDependencies=no
After=local-fs.target
Before=network-online.target

[Service]
Type=oneshot
RemainAfterExit=yes
TimeoutStartSec=2min
ExecStart=/bin/sh -ec '\
  for i in $(ifquery --list --exclude lo --allow auto); do INTERFACES="$INTERFACES$i "; done; \
  [ -n "$INTERFACES" ] || exit 0; \
  while ! ifquery --state $INTERFACES >/dev/null; do sleep 1; done; \
  for i in $INTERFACES; do while [ -e /run/network/ifup-$i.pid ]; do sleep 0.2; done; done'

[Install]
WantedBy=network-online.target

This is the service file as present on an Ubuntu 15.04 system, but with the [Install] section added in to make things a little easier. I'm hoping that the behavior of ifup in Ubuntu 15.04 is the same as the behavior of ifup in Debian Jessie. If not, some modification will be necessary (particularly with the last line).

Then, run sudo systemctl enable ifup-wait-all-auto.service. After rebooting your computer, you should see that the network-online.target is reached after the interfaces are brought up (at least).

5
  • Thanks for effort, let me try it now and I'll give you feedback
    – 10robinho
    Jul 23, 2015 at 1:13
  • I've ended up running slightly modified version ExecStart = /bin/bash -c 'while [ -z "$(hostname -I)" ]; do sleep 1; done;'. It depends on hostname to check if IP address has been assigned.
    – luka5z
    May 1, 2017 at 20:04
  • Don't try spin doctor it. it's not because he's using /etc/network/interfaces. It's because systemd is so sloppy and the work is offloaded to every user instead of solving the problem where it was created. Sep 19, 2017 at 22:32
  • 1
    fwiw, the ifup-wait-all-auto.service has been dropped in ifupdown version 0.8.5ubuntu1: ”Drop ifup-wait-all-auto.service. This has been implemented more elegantly by making network-online.target Wants=networking.service directly.“ [changelog]
    – myrdd
    Jul 10, 2018 at 5:26
  • 2
    In Debian the service is called ifupdown-wait-online.service.
    – teissler
    Jan 5, 2023 at 14:39
7

I once found an answer on Github that solved it by continuously trying to ping a server. Only when the ping comes through, the service continues:

[Service]
ExecStartPre=/bin/sh -c 'until ping -c1 google.com; do sleep 1; done;'
ExecStart=<your command>

I replaced google.com with my own server because my main script needed to connect to my server.

1
  • awesome! simple, short and effective!
    – Nicolas
    Feb 4, 2021 at 21:33
2

Attention! Just figured out it on a Raspbian Jessie : remove ALL commented lines in /etc/network interfaces and it will work! It seems to be a parsing bug =) In my specific case I've left commented iface eth0 inet dhcp and just forgot about it eons ago, but after upgrade to Raspbian Jessie and rebuilding a kernel I've got very odd behaviour : it used DHCP and refused to make a tuning from /etc/network/interfaces. So I've stripped it out of any comments - just working lines, reboot - and it works! NO SCRIPT PATCHING/EDITING NEEDED!

3
  • Interestin, I need to try this. Although it doesn't make much sense :)
    – 10robinho
    Jan 18, 2016 at 12:10
  • 2
    Do you have any references about this? I'd like to read the bug report(s) and see the buggy code.
    – ʇsәɹoɈ
    Feb 9, 2017 at 22:27
  • No, I haven't opened a bug ticket. To reproduce it just add some comments in your /etc/network/interfaces file - it will fire up if it's still there. Feb 9, 2017 at 23:10
2

None of the previous answers worked for me. The correct approach was to change allow-hotplug to auto in /etc/network/interfaces:

# The primary network interface
allow-hotplug enp0s25
iface enp0s25 inet dhcp

to:

# The primary network interface
auto enp0s25
iface enp0s25 inet dhcp
1

Per https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/ the recommended way to start a service AFTER networking is level is to use "network-online.target" in the .service file:

 "After=network-online.target"
 "Wants=network-online.target"

However after using "network-online.target" and my service failing because networking wasn't fully level, I discovered there's a bug (https://github.com/coreos/bugs/issues/1966) with it: not guaranteed to be 100% infallible.

Indeed, where dynamic networking configuration tools such as "NetworkManager" are used as in this case, the state of networking can never be 100% precise or predictable. Apparently from the link describing the bug, "network-online.target" can behave inconsistently depending on different applications it's used with.

Workaround:
You need to analyze the start-up order of services and use one that starts later than "network-online.target":

 systemd-analyze plot > /home/pi/graph.svg

This is an iterative process changing the targets incrementally to later and later services until you find the one that ensures networking is level and your service starts without error. In my own case I even had to put a sleep 10 in my script the SystemD service called.

1

This bug was introduced 7 years ago and was fixed two years ago. These lines were added to NetworkManager.service

# We want to enable NetworkManager-wait-online.service whenever this service
# is enabled. NetworkManager-wait-online.service has
# WantedBy=network-online.target, so enabling it only has an effect if
# network-online.target itself is enabled or pulled in by some other unit.
Also=NetworkManager-wait-online.service

If you come here then you are probably using older OS and should manually enable NetworkManager-wait-online.service.

Run systemctl enable NetworkManager-wait-online.service

You must log in to answer this question.

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