11

I have a user service in ~/.config/systemd/user/example.service like so:

[Unit]
Description=Example service
After=network.target

[Service]
ExecStart=/bin/bash -c 'host google.com > /var/tmp/example'

[Install]
WantedBy=default.target

The actual service I'm trying to control actually does something useful and accesses the network, of course; this is just a simplified example.

The service is enabled via systemctl --user enable example.service which creates the symlink ~/.config/systemd/user/default.target.wants/example.service pointing to ~/.config/systemd/user/example.service.

With this setup, and with systemd user sessions enabled as described on the Arch Wiki, the service is started as my user upon startup. However, it is not actually started after the network is set up; instead, it seems to start immediately, since /var/tmp/example contains:

;; connection timed out; no servers could be reached

(And the actual service that I'm trying to control can't reach the network either, and fails with similar name-lookup errors)

This means that the service doesn't actually run after network.target. How do I make it wait for network.target before running?

2 Answers 2

3

Forget the network.target. man systemd.special says:

network.target
       systemd automatically adds dependencies of type After for
       this target unit to all SysV init script service units
       with an LSB header referring to the $network facility.

So, this target is primarily a compatibility hack for SysV init scripts.

Assuming that your network connection is handled by NetworkManager you were of course right to depend on this target because NetworkManager.service defines Before=network.target. But this only means that NetworkManager has been started, not that the network connection is actually established. That may take a while (dhcp roundtrips, wifi handshake, etc.) and is entirely the business of NetworkManager. At least on my system (F18) there is a service called NetworkManager-wait-online. It uses the nm-online utility program to block until there is an active connection established. Try to Require, Before that in your Unit definition or use that tool on its own.

1
  • I'm using dhcpcd (NetworkManager is way overkill for a server, in my opinion), but either way I haven't found a way to depend on a forking executable in a service definition...
    – dflemstr
    Feb 3, 2013 at 10:32
10

I was having the same problem, with a userland backup script that needs access to the internet. I solved it by adding ~/.config/systemd/user/wait-for-network.service that just pings google.com until it is reachable:

[Unit]
Description=Ping a server on the internet until it becomes reachable

[Service]
Type=oneshot
ExecStart=/bin/bash -c 'while ! ping -c1 google.com; do sleep 1; done'
TimeoutStartSec=60s

Then I made my backup script depend on it like this:

[Unit]
Description=...
Requires=wait-for-network.service
After=wait-for-network.service

This works regardless of whether you use NetworkManager or some other means to establish the connection.

You must log in to answer this question.

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