How does systemd maintain the compatibility with SystemV init scripts?

systemd is a system and service manager for Linux operating systems. When a systemd Linux system starts, systemd runs as first process on boot (as PID 1), and it acts as init system that brings up and maintains userspace services. systemd uses “units” (12 different types) to manage services related to system boot-up and maintenance. These units are defined and configured in unit configuration files, whoese syntax and basic set of options is described in systemd.unit(5).

If you are moving from a SystemV init system to a systemd system, you might be wondering how it works with the legacy init scripts. Usually you have two choices:

1. Define the service with a systemd native unit configuration file.

Or

2. do nothing but leave your init script under /etc/init.d/

And as a newbie of systemd, likely you will choose the option 2. Then how does systemd work with this option — how does systemd maintain the compatibility with SystemV init scripts?

Basically “systemd is compatible with the SysV init system to a large degree: SysV init scripts are supported and simply read as an alternative (though limited) configuration file format. The SysV /dev/initctl interface is provided, and compatibility implementations of the various SysV client tools are available. In addition to that, various established Unix functionality such as /etc/fstab or the utmp database are supported.

The systemd system manager reads unit configuration from various directories. Packages that want to install unit files shall place them in the directory returned by “pkg-config systemd –variable=systemdsystemunitdir“. Other directories checked are /usr/local/lib/systemd/system and /usr/lib/systemd/system. User configuration always takes precedence. pkg-config systemd –variable=systemdsystemconfdir returns the path of the system configuration directory. Packages should alter the content of these directories only with the enable and disable commands of the systemctl(1) tool. Full list of directories is provided in systemd.unit(5).

On my Oracle Linux 7 system,

root@joetestdb:# pkg-config systemd --variable=systemdsystemunitdir
/usr/lib/systemd/system

Unit files are loaded from a set of paths determined during compilation, described in the table below. Unit files found in directories listed earlier override files with the same name in directories lower in the list.

Table from man page of systemd.unit — Load path when running in system mode (–system):

 ┌────────────────────────┬─────────────────────────────┐
 │Path                    │ Description                 │
 ├────────────────────────┼─────────────────────────────┤
 │/etc/systemd/system     │ Local configuration         │
 ├────────────────────────┼─────────────────────────────┤
 │/run/systemd/system     │ Runtime units               │
 ├────────────────────────┼─────────────────────────────┤
 │/usr/lib/systemd/system │ Units of installed packages │
 └────────────────────────┴─────────────────────────────┘

Another table you can find from the link in the Reference section:

PathDescription
/usr/lib/systemd/system/systemd unit files distributed with installed RPM packages.
/run/systemd/system/systemd unit files created at run time. This directory takes precedence over the directory with installed service unit files.
/etc/systemd/system/systemd unit files created by systemctl enable as well as unit files added for extending a service. This directory takes precedence over the directory with runtime unit files.
Oracle Linux 7 systemd unit files locations

some units are dynamically created via a systemd.generator. So basically there is a specific systemd.generator called systemd-sysv-generator which is located under /usr/lib/systemd/system-generators/. It is a generator that creates wrapper .service units for SysV init scripts in /etc/init.d/* at boot time and when configuration of the system manager is reloaded. This will allow systemd(1) to support them similarly to native units.

SysV runlevels have corresponding systemd targets (runlevelX.target). Wrapper unit that is generated will be wanted by those targets which correspond to runlevels for which the script is enabled.

systemd does not supports SysV scripts as part of early boot, so all wrapper units are ordered after basic.target.

For a init script under /etc/init.d/, you will find the wrapper .service under /run/systemd/generateor.late/

For example, I put my Oracle startup script under /etc/init.d/ called “dbora“, the generator will read the chkconfig header (or Linux Standard Base (LSB) header if provided) and create the wrapper file: /run/systemd/generator.late/dbora.service:

root@joetestdb:# cat /run/systemd/generator.late/dbora.service
 Automatically generated by systemd-sysv-generator
 [Unit]
 Documentation=man:systemd-sysv-generator(8)
 SourcePath=/etc/rc.d/init.d/dbora
 Description=SYSV: Oracle auto start-stop script
 Before=runlevel3.target
 Before=runlevel4.target
 Before=runlevel5.target
 Before=shutdown.target
 After=network-online.target
 After=jexec.service
 After=network.service
 After=rhnsd.service
 Conflicts=shutdown.target
 [Service]
 Type=forking
 Restart=no
 TimeoutSec=5min
 IgnoreSIGPIPE=no
 KillMode=process
 GuessMainPID=no
 RemainAfterExit=yes
 ExecStart=/etc/rc.d/init.d/dbora start
 ExecStop=/etc/rc.d/init.d/dbora stop

 root@joetestdb:# head -3 /etc/rc.d/init.d/dbora
 !/bin/sh
 chkconfig: 345 99 10
 description: Oracle auto start-stop script

Reference:

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/configuring_basic_system_settings/managing-services-with-systemd_configuring-basic-system-settings

Leave a comment