22

I have written a couple of systemd user service files which I want users to enable and which need a working network connection. I thought that would be as easy as:

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

However, the services seem to start too early, and in journalctl I see:

network-online.target: Cannot add dependency job, ignoring: Unit network-online.target failed to load: No such file or directory.

Then I searched more and tried

Wants=network.target
After=network.target

and did sudo systemctl enable systemd-networkd-wait-online.service.

Now I have in journalctl:

network.target: Cannot add dependency job, ignoring: Unit network.target failed to load: No such file or directory.

And again the service starts too early.

Is that message supposed to be there? How can I debug my problem?


EDIT: the reason is simple and specifically stated in the Arch Wiki:

systemd --user runs as a separate process from the systemd --system process. User units can not reference or depend on system units.

This forum post seems to suggest a simple solution: I should link the necessary system unit as a user, thus creating a symlink to it available on the unit search path.

After doing that, I don't see any No such file or directory messages, however, I still can't make the services actually run after the network is online. I have tried linking network.target, network-online.target and systemd-networkd-wait-online.service, setting my units to depend on each of them, with no success. When I check the linked unit's status in user mode, they are all some of them are dead, e.g.:

$ systemctl --user status network.target
● network.target - Network
   Loaded: loaded (/usr/lib/systemd/system/network.target; linked; vendor preset: enabled)
   Active: inactive (dead)
     Docs: man:systemd.special(7)
           http://www.freedesktop.org/wiki/Software/systemd/NetworkTarget
$ systemctl status network.target
● network.target - Network
   Loaded: loaded (/usr/lib/systemd/system/network.target; static; vendor preset: disabled)
   Active: active since Sat 2015-07-18 19:20:11 MSK; 3h 35min ago
     Docs: man:systemd.special(7)
           http://www.freedesktop.org/wiki/Software/systemd/NetworkTarget

Jul 18 19:20:11 calc-server systemd[1]: Reached target Network.
Jul 18 19:20:11 calc-server systemd[1]: Starting Network.

However, I can see network-online.target active in user mode after linking it:

$ systemctl --user status network-online.target
● network-online.target - Network is Online
   Loaded: loaded (/usr/lib/systemd/system/network-online.target; linked; vendor preset: enabled)
   Active: active since Sun 2015-07-19 00:35:38 MSK; 2min 48s ago
     Docs: man:systemd.special(7)
           http://www.freedesktop.org/wiki/Software/systemd/NetworkTarget

Jul 19 00:35:38 calc-server systemd[469]: Reached target Network is Online.
Jul 19 00:35:38 calc-server systemd[469]: Starting Network is Online.
11
  • I hope you'll have an answer.
    – user123418
    Jul 18, 2015 at 16:41
  • @Deleteme Thanks, I think I found the cause of this (see update), but not how to solve the problem. Jul 18, 2015 at 19:59
  • Did you every find a solution to this problem? Also, I notice you emphasise that only some linked units are dead. Which are the ones that worked, and how do they differ?
    – Sparhawk
    Nov 2, 2015 at 6:44
  • @Sparhawk unfortunately not. As a workaround, I just use timers set to several seconds after boot. The question has an example: network-online target is active after linking, and network target is not. Nov 2, 2015 at 8:55
  • Perhaps I misunderstand, but I'm looking for something to fire every time the network resumes, to check my email after resuming from suspend. I thought this would be the way to do it. I see the examples now. I thought you meant some custom services fired and some did not. However, I see now you are talking about the user versions of the network targets.
    – Sparhawk
    Nov 2, 2015 at 9:07

3 Answers 3

6

As this topic is No1 in google search results I share an alternate solution for all who will face the same problem.

In my system I added a simplified equivalent to /lib/systemd/system/systemd-networkd-wait-online.service (which is WantedBy=network-online.target) and stored it in user services directory:

[Unit]
Description=User Wait for Network to be Configured

[Service]
Type=oneshot
ExecStart=/lib/systemd/systemd-networkd-wait-online
RemainAfterExit=yes

[Install]
WantedBy=default.target

Then I made my user services to depend on this new one:

Wants=networkd-wait-online.service
After=networkd-wait-online.service

However, Wants= does not seem to be required due to WantedBy=default.target. You can remove WantedBy=default.target so this makes network-wait-online.service optional, but you certainly need Wants=network-wait-online.service then.

Original service systemd-networkd-wait-online.service contains more dependencies, but they do not seem to be working in user context. Someone may provide user running equivalents for all of these dependencies, e.g. by using systemctl --user link for network.target and network-online.target as in other suggestions here, but I decided to keep it simple ;)

Note that despite of making a symlink to system service you do NOT tell your systemd --user manager to use some events from systemd --system manager to watch on a system service state, but make it to run another instance of this service from user context.

3

Since you cannot depend on a system service, your only solution is to provide a user service that detects whether the network is online. (Or make your services system services.) Details for a "detect-online" user service would depend on your definition of "online". It could wait for a ping to 8.8.8.8 to succeed, for instance. Or for a DNS name resolution to succeed. For instance, in a similar situation with vpnc, I wait for a ping to a vpn IP to succeed.

Then you can make your user services depend on (After=) your detect-online user service.

#!/bin/sh

host="${1:-8.8.8.8}"

pingcheck() {
  ping -n -c 1 -w 5 $1 >/dev/null 2>&1
}

# Do you want a timeout ?
while :; do
  pingcheck ${host} && exit 0
  sleep 10
done
1
  • Thank you, this seems reasonable and simple enough. But if 10 users enable my user service, there will be 10 instances pinging the same server simultaneously, which seems a bit redundant. In practice this is probably not at issue, but I was asking this in the hope of getting a single "online flag" available to all user services. No better solutions have yet been suggested, though. Dec 16, 2015 at 0:25
1

I would recommend to test something like this:

# /etc/systemd/system/foo.service
[Unit]
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/bin/logger -t foo "testing online target"

[Install]
WantedBy=multi-user.target

Followed by:

# systemctl daemon-reload && systemctl enable foo.service
1
  • 9
    But this is a system service, and I am trying to set up a user service. Dec 3, 2015 at 7:01

You must log in to answer this question.

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