Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

systemd adding service into multi-user.target.wants folder only works as a symlink [closed]

Tags:

linux

systemd

I have been adding some systemd services. I started off with my services being symlinks from:

/etc/systemd/system/multi-user.target.wants/myservice.service -> /home/myservice.service

This seems to work ok. but if I remove the symlink and make it a conrete file then the service does not load (systemctl daemon-reload does not find it).

However if I move the service into /etc/systemd/system/myservice.service then it is working fine.

So, it appears that for a service to work within the multi-user.target.wants it needs to be a symlink. Why is that? is there a way around that?

I have seen symlinks to ../myservice.service from within the multi-user.target.wants before... I am guessing I have stumbled on the reason for that!?

like image 503
code_fodder Avatar asked Aug 14 '19 14:08

code_fodder


1 Answers

Only symlinks are allowed in .wants/ and .requires/ directories. By custom, the symlink is made to the actual unit file in /etc/systemd/system/, /usr/lib/systemd/system/, or one of the other unit directories. But systemd doesn't care too much about the symlink target. (The target directory of the symlink is ignored completely. The final component of the symlink target is checked and newer systemd will warn if the target name does not match the symlink name, but will still accept it). The presence of the symlink tells that the Wants or Requires dependency needs to be created.

The .wants/ and .requires/ directories are a mechanism to declare a dependency. But to actually load the unit, systemd needs to find the unit file. It needs to be in one of the directories (/etc/systemd/system/, /usr/lib/systemd/system/, etc.).

You might be confused by the fact that older systemd would follow unit symlinks from .wants/ or .requires/ and load the unit file. This was problematic for two reasons: the first is that systemd has a priority order for the directories, and it's supposed to load the unit file in the directory with the highest priority. But the symlink might point to a unit file in a directory with lower priority. To remain consistent systemd must ignore the symlink target, and search the directories in order. The second reason is that the symlink might point to file outside of the search path. If systemd would allow loading of such units, those units could be loaded as a dependency of another unit, but when asked to load the unit directly, systemd would be unable to find it. Newer systemd never follows such symlinks.

The second reason in the previous paragraph is also why systemd does not allow real files in .wants/ or .requires/: the unit would only be loadable as a dependency of another unit, but not directly.

There are two correct ways to handle this:

  1. move the unit file to one of the unit directories, e.g. /etc/systemd/system/myservice.service, and symlink to it from multi-user.target.wants/.
  2. keep the unit file somewhere else, e.g. ~/myservice.service, and symlink to it from one of the unit directories, e.g. /etc/systemd/system/myservice.service, and symlink to that symlink from multi-user.target.wants/.

See also systemctl link and systemctl enable which can create those symlinks for you.

like image 159
zbyszek Avatar answered Oct 23 '22 22:10

zbyszek