Is /etc/init.d the default search path that the systemd generator uses to convert native SysV script to unit files, and falls back to /etc/rc?.d or vice versa?

From this answer by @JdeBP:

This program is a generator, a type of ancillary utility whose job is to create service unit files on the fly, in a tmpfs where three more of those nine directories (which are intended to be used only by generators) are located. systemd-sysv-generator generates the service units that run the System V rc scripts from /etc/init.d, if it doesn't find a native systemd service unit by that name already existing in the other six locations.

But, How Linux Works book mentions something different:

  1. First, systemd activates runlevel<N>.target, where N is the runlevel.
  2. For each symbolic link in /etc/rc<N>.d, systemd identifies the script in /etc/init.d.
  3. systemd associates the script name with a service unit (for example, /etc/init.d/foo would be foo.service).
  4. systemd activates the service unit and runs the script with either a start or stop argument, based on its name in rc<N>.d.
  5. systemd attempts to associate any processes from the script with the service unit.

As far as I can tell, the procedure goes in the following way: systemd finds SysV scripts in /etc/init.d and depending on the runlevel, systemd decides to start or stop the scripts according to the symlink name (K* or S*) from /etc/rc?.d. This makes sense, because once the SysV script is converted into a native systemd unit file, the decision to start or to stop the process has to be obtained from /etc/rc?.d. For example, I'm running Ubuntu 17.04:

$ ls -l /etc/rc5.d
lrwxrwxrwx 1 root root 15 Aug  4 00:10 S01acpid -> ../init.d/acpid
lrwxrwxrwx 1 root root 17 Aug  4 00:10 S01anacron -> ../init.d/anacron
lrwxrwxrwx 1 root root 16 Aug  4 00:10 S01apport -> ../init.d/apport
lrwxrwxrwx 1 root root 22 Aug  4 00:10 S01avahi-daemon -> ../init.d/avahi-daemon
...many more...

I can see that all of the symlinks to the scripts have the same execution order 01, and this is done intentionally so to exploit parallelism in systemd, so systemd-sysv-generator uses /etc/rc?.d to also determine the order of the dependencies (e.g, Before, After).

Since the LSB header within scripts determine the runlevel in which scripts are run, I'm more to likely lean towards the idea that systemd-sysv-generator defaults to /etc/init.d to decide which scripts to start in which runlevel instead of /etc/rc?.d, except if that can't be determined from the LSB header within the script. Are my assumptions right?


LSB headers[2] in SysV init scripts are interpreted, and the ordering specified in the header is turned into dependencies between the generated unit and other units. The LSB facilities "$remote_fs", "$network", "$named", "$portmap", "$time" are supported and will be turned into dependencies on specific native systemd targets.

But the man page doesn't mention anything related to the case where there's no LSB header. Pretty much over complicated :.

  • Possible duplicate of How does systemd use /etc/init.d scripts? – thecarpy Sep 24 '17 at 19:55
  • @thecarpy it's certainly related - and the OP has even referenced this same question/answer in their own question (above). But they're not duplicates; this one's asking about the search path, and that's not defined in any of the answers of your proposed duplicate – roaima Sep 24 '17 at 20:20
  • 1
    §6.4.8 of M. Ward's book is in need of some heavy revision for the 3rd edition. There are a lot of errors in there, starting with the incorrect statement that systemd activates any runlevel targets. systemd does not work that way. – JdeBP Sep 25 '17 at 4:52
  • @JdeBP I wonder why systemd is one of the most misunderstood inits. In the answer you've provided in your comment, you state that systemd-sysv-generator: "merges the /etc/rc[234].d directories into just the one Wanted-By relationship to multi-user.target in generated service units." What about the LSB headers? AFAIK, the LSB headers used to determine the order and the dependencies of the scripts in /etc/init.d. Without LSB, the fallback option is rc?.d I don't really quite understand the whole process involved here. Red Hat guys give us magic but don't tell us how it works! – direprobs Sep 25 '17 at 8:01

I marked your question as a duplicate.

Read JdeBP great answer here: How does systemd use /etc/init.d scripts?

Received wisdom is that the System V rc scripts must have an LSB header, and are run in parallel without honouring the priorities imposed by the /etc/rc?.d/ system. This is incorrect on all points.

In fact, they don't need to have an LSB header, and if they do not systemd-sysv-generator can recognize the more limited old RedHat comment headers (description:, pidfile:, and so forth). Moreover, in the absence of an LSB header it will fall back to the contents of the /etc/rc?.d symbolic link farms, reading the priorities encoded into the link names and constructing a before/after ordering from them, serializing the services. Not only are LSB headers not a requirement, and not only do they themselves encode before/after orderings that serialize things to an extent, the fallback behaviour in their complete absence is actually significantly non-parallelized operation.

The reason that /etc/rc3.d didn't appear to matter is that you probably had that script enabled via another /etc/rc?.d/ directory. systemd-sysv-generator translates being listed in any of /etc/rc2.d/, /etc/rc3.d/, and /etc/rc4.d/ into a native Wanted-By relationship to systemd's multi-user.target. Run levels are "obsolete" in the systemd world, and you can forget about them.

The question of what the search path is, is in fact actually addressed by what you quoted in your question:

systemd-sysv-generator generates the service units that run the System V rc scripts from /etc/init.d, if it doesn't find a native systemd service unit by that name already existing in the other six locations.

In more detail:

  • For the scripts themselves:
    • systemd-sysv-generator looks for an environment variable named SYSTEMD_SYSVINIT_PATH.
    • Each directory is scanned for regular files that have the owner execute permission bit set on, with earlier directories in the path overriding later ones (a mechanism not really exercised in the default case of just the one directory in the search path) and the existence of service units with the same names inhibiting the generation of these nonce ones.
  • For the "symbolic link farms":
    • There is a similar environment variable named SYSTEMD_SYSVRCND_PATH.
    • Each directory is scanned for subdirectories named rc[2345].d, which are in turn scanned for directory entries that begin with S and two decimal digits and that are at least 4 characters long. The directory entries are not dereferenced.

Notice that systemd-sysv-generator

  • does not look at the K* stuff;
  • does not check that the symbolic link farms are actually filled with symbolic links (They could be character special files or FIFOs for all that it cares, as it only looks at the names.); and
  • does not process the runlevel information from LSB comments (i.e. the Default-Start: and Default-Stop: comments).

Remember, in respect of the third point, that in vanilla van Smoorenburg rc the runlevel information from LSB comments does not directly control bootstrap/shutdown behaviour. That's the remit of the symbolic link farm directories. Describing van Smoorenburg rc in systemd terminology: the symbolic link farms are the service enable controls, that determine what services are automatically started at bootstrap; whereas the Default-Start: and Default-Stop: comments are (very approximately) service preset controls, that are turned into the enable controls.

  • This is the question I linked in my question though. There's contradiction between the book I'm reading and the answer. I can't assert which one is right! – direprobs Sep 24 '17 at 20:08
  • @direprobs Part 5 in your quote is nonsense. Systemd does not attempt to adopt processes started by some other system. I think you can write off the book for reliable technical details, after all it does not mention LSB headers. – sourcejedi Sep 24 '17 at 21:21

I just did some trial runs on this to find out more, kind of a follow on to thecarpy's answer.

From what I can tell systemd-sysv-generator does the following: if there's a script in /etc/init.d it checks /etc/rc?.d/ and sees if it's part of "any runlevel." If it is, it adds it to that runlevel in the systemd hierarchy. It also gets Description information from the LSB headers in the init.d file. It also adds any hierarchy information from LSB

# Required-Start: bar

type line.

Things get weirder from there. If you run systemctl enable my_service it basically "farms out" to chkconfig to adjust the /etc/rc?.d directories, then runs systemctl daemon-reload after that to soak up the new information. However it runs it like /sbin/chkconfig my_service on (note that trailing on) which instructs it to turn it on for runlevels 2-5, and ignore the levels specified anywhere in the init.d file. However if you run chkconfig manually like chkconfig --add my_service then it respects the levels specified in the script.

Also weird: if there is no runlevel specified in the init.d file and it isn't yet symlinked in any /etc/rc?.d folder, then the systemd-sysv-generatoreems to assume you want it to be started in runlevel 4 and 5.
Plus, even if your default starting runlevel is 3, that's the same as 4 and 5. So basically it seems to assume you want to start it, no matter what, despite it not being symlinked in any rc?.d dirs.

Also note if a service is "disabled", on older versions of systemd it won't show up in typical lists.

Also of note, there are two ways to specify the runlevel, both chkconfig and systemctl seem to "prefer LSB over the "old style"

chkconfig man page says:

Each service which should be manageable by chkconfig needs two or more commented lines added to its init.d script. 
# chkconfig: 2345 20 80
# description: Saves and restores system entropy pool for \
#              higher quality random number generation.
chkconfig also supports LSB-style init stanzas, and will apply them in preference to "chkconfig:" lines where available. A LSB stanza looks like:

# Provides: foo
# Required-Start: bar
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Description: Foo init script

So in general that book doesn't seem quite in a right oder. The systemd-sysv-generator runs very early on in the boot phase, and sets up services (as specified above) and also enables them in the "run level equivalent" target if it deems they should be autorun. Then the boot proceeds, and starts up all services in the normal systemd order.

So, to answer the question, it uses a combination of etc/init.d and/etc/rc?.deach timesystemd` loads or reloads. In whacky ways.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.