Book Excerpt: A Practical Guide to Fedora and Red Hat Enterprise Linux
The init Daemon
The init daemon is the system and service manager for Linux. It is the first true process Linux starts when it boots and as such, has a PID of 1 and is the ancestor of all processes. The init daemon has been around since the early days of UNIX, and many people have worked to improve it. The first Linux init daemon was based on the UNIX System V init daemon and is referred to as SysVinit (System V init daemon).
Because SysVinit does not deal well with modern hardware, including hotplug devices, USB hard and flash drives, and network-mounted filesystems, Fedora/RHEL recently replaced it with the Upstart init daemon (http://upstart.ubuntu.com/ and http://upstart.ubuntu.com/wiki). Fedora 15 has moved past Upstart to systemd init daemon, which is described next. Several other replacements for SysVinit are also available. One of the most prominent is initng (http://initng.sourceforge.net/trac). In addition, Solaris uses SMF (Service Management Facility), and MacOS uses launchd.
The systemd init Daemon (Fedora)
The name systemd comprises system, which systemd manages, followed by d. Under UNIX/Linux, daemon names frequently end in d: systemd is the system daemon. At boot time, systemd renames itself init, so you will not see a process named systemd. However, init is simply a link to systemd:
$ ls -l /sbin/init lrwxrwxrwx. 1 root root 14 04-22 08:47 /sbin/init -> ../bin/systemd
The name is also a play on words with System D, a reference to the French dérouillard (to untangle) or démerder. System D is a manner of responding to challenges that requires fast thinking, adapting, and improvising.
The systemd init daemon is a drop-in replacement for SysVinit; most of the administration tools that worked with SysVinit and Upstart work with systemd. Although systemd is new, most of the user interfaces pertinent to administrators will remain stable (http://www.freedesktop.org/wiki/Software/systemd/InterfaceStabilityPromise). A GUI to systemd is under development.
Use apropos to list man pages that pertain to systemd (apropos systemd). Some of the most interesting of these are systemd, systemctl, systemd.unit, and systemd.special.
systemd home page: http://www.freedesktop.org/wiki/Software/systemd
Fedora systemd home page: fedoraproject.org/wiki/Systemd
Fedora systemd feature list: fedoraproject.org/wiki/Features/systemd
SysVinit to systemd conversion notes: fedoraproject.org/wiki/SysVinit_to_Systemd_Cheatsheet
List of services that run natively under systemd: http://fedoraproject.org/wiki/User:Johannbg/QA/Systemd/compatability
Blog about systemd by its creator, Lennart Poettering: 0pointer.de/blog/projects/systemd.html
systemd stability promise: http://www.freedesktop.org/wiki/Software/systemd/InterfaceStabilityPromise
Service Units and Target Units
The systemd init daemon is based on the concept of units, each of which has a name and type. Typically information about a unit is stored in a file that has the same name as the unit (e.g., dbus.service). The types of units are service, socket, device, mount, automount, target, snapshot, timer, swap, and path. This section discusses service and target units, which are critical to controlling daemons and runlevel under systemd.
A service unit refers to a daemon (service) that systemd controls, including those controlled natively by systemd and those controlled by systemd via SysVinit scripts. For example, systemd controls the ntpd daemon natively via the ntpd.service service unit.
A target unit groups other units. Of concern in this section are targets that control the system runlevel. By default, Fedora activates graphical.target, which brings the system to a runlevel that equates to what was formerly called runlevel 5 (multiuser graphical mode). Activating multi-user.target brings the system to what was formerly called runlevel 3 (multiuser textual mode).
Terminology: server, service, daemon
A daemon, such as ntpd or cupsd, provides a service that runs on a server. The daemon itself is also sometimes referred to as a server. These three terms can be used interchangeably.
The systemd init daemon does not support runlevels the way SysVinit did. It supports target units, which parallel runlevels but are different. To ease the transition, this book continues to use the term runlevel to refer to target units. One difference between SysVinit runlevels and systemd target units is that the former can be changed only when the system changes runlevels while the latter can be activated by any of a large group of triggers. Another difference is that a systemd-based system can activate more than one target unit at a time, allowing the system to be in more than one runlevel at a time. For example, graphical.target pulls in multi-user.target so they are both active at the same time.
systemd runlevels differ from SysVinit runlevels - For consistency and clarity during the transition from SysVinit to systemd, this book refers to systemd target units as runlevels. Target units are not true runlevels, but they perform a function similar to the function performed by SysVinit runlevels.
Wants and Requires
Under systemd, the terms wants and requires specify units that are to be activated when the unit that wants or requires the other unit is activated. A unit that requires another unit will not start if the other unit is not available and will quit if the other unit becomes unavailable while the first unit is active. Wants is similar to requires, except a unit that wants another unit will not fail if the wanted unit is not available.
The following systemctl show command displays the Requires properties of the graphical.target unit. It shows that graphical.target requires multi-user.target:
$ systemctl show --property "Requires" graphical.target Requires=multi-user.target
This relationship causes systemd not to start graphical.target if multi-user.target is not available. It means graphical.target requires units that multi-user.target requires and wants units that multi-user.target wants. Because of this relationship, multi-user.target (runlevel) is active at the same time graphical.target (runlevel) is active.
You can also use the systemctl show command to display the Wants properties of a target:
$ systemctl show --property "Wants" multi-user.target Wants=systemd-update-utmp-runlevel.service NetworkManager.service ... (END) q
The list is long. Although systemctl passes the output through a pager, it runs off the right edge of the screen. When the command displays (END), press q to return to the shell prompt. Sending the output through the fmt text formatter with a line-length specification of 10 displays the list one service per line:
$ systemctl show --property "Wants" multi-user.target | fmt -10 Wants=systemd-update-utmp-runlevel.service NetworkManager.service abrtd.service ntpd.service mcelog.service rsyslog.service ...
To see if a target wants a specific service, send the output of the previous command through grep:
$ systemctl show --property "Wants" multi-user.target | fmt -10 | grep ntpd ntpd.service ntpdate.service
The output shows that multi-user.target wants the ntpd.service service. Because graphical.target requires multi-user.target and multi-user.target wants ntpd.service, systemd will start ntpd.service when the system enters the runlevel defined by graphical.target.
The services wanted by a runlevel target appear in directories named .wants under the /etc/systemd/system directory:
$ ls -ld /etc/systemd/system/.wants ... drwxr-xr-x. 2 root root 4096 04-20 17:10 /etc/systemd/system/graphical.target.wants drwxr-xr-x. 2 root root 4096 04-20 17:10 /etc/systemd/system/multi-user.target.wants ...
The following command lists the runlevel targets that want ntpd.service:
$ ls /etc/systemd/system/.wants/ntpd.service /etc/systemd/system/multi-user.target.wants/ntpd.service
As explained in the previous section, you can also display this information using the systemctl show command.
The directory hierarchy with its root at /etc/systemd/system controls the persistent runlevel of the system. That is, this directory hierarchy specifies which daemons will be started when the system boots or otherwise changes runlevel or when the daemon is activated for another reason.
All service unit files are kept in the /lib/systemd/system directory. All plain files in the /etc/systemd/system hierarchy are links to files in the /lib/systemd/system hierarchy. For example, ntpd.service shown in the preceding example is a link to the appropriate service unit file in /lib/systemd/system:
$ ls -l /etc/systemd/system/multi-user.target.wants/ntpd.service lrwxrwxrwx. 1 root root 32 04-08 14:34 /etc/systemd/system/multi-user.target.wants/ntpd.service -> /lib/systemd/system/ntpd.service
The service unit file provides systemd with information it needs to start the service and specifies the system runlevel target that wants the service:
$ cat /lib/systemd/system/ntpd.service [Unit] Description=Network Time Service After=syslog.target ntpdate.service [Service] EnvironmentFile=/etc/sysconfig/ntpd ExecStart=/usr/sbin/ntpd -n -u ntp:ntp $OPTIONS [Install] WantedBy=multi-user.target
When you instruct systemd to start a service when the system boots (make the service persistent), it places a link to the service file in the directory specified by _WantedBy in the service file. Continuing with the example, systemd places a link to ntpd.service in the multi-user.target.wants directory as shown previously. When you instruct systemd to not start a service when the system boots, it removes the link. “Setting the Persistent State of a Daemon (Service)” explains how to use systemctl to make these changes.
The persistent (default) runlevel is also controlled by a link:
$ ls -l /etc/systemd/system/default.target lrwxrwxrwx. 1 root root 36 04-20 10:07 /etc/systemd/system/default.target -> /lib/systemd/system/runlevel5.target
See “Setting the Persistent Runlevel” for more information.
Custom Service Files
As explained in the previous section, files in the /etc/systemd/system directory hierarchy are symbolic links to files in the /lib/systemd/system directory hierarchy. The systemd init daemon treats files in the /etc/systemd/system directory hierarchy and files in the /lib/systemd/system directory hierarchy the same way, with files in /etc/systemd/system overriding files with the same name in /lib/systemd/system. An important difference between these directory hierarchies is that /lib/systemd/system is managed by yum/RPM while /etc/systemd/system is managed by the system administrator.
Put custom service files in the /etc/systemd/system hierarchy. If you want to modify a service file, copy it from the /lib/systemd/system hierarchy to the /etc/systemd/system hierarchy and edit the copy. The custom file in the /etc/systemd/system hierarchy will not be overwritten by yum/RPM and will take precedence over a file with the same name in the /lib/systemd/system hierarchy.
Determining if systemd runs a Daemon Natively
To ease migration from a SysVinit and Upstart to systemd and to provide compatibility with software intended for other distributions, systemd can control daemons via SysVinit scripts. You can use the systemctl status command to determine if systemd is controlling a daemon natively or via a SysVinit script. Following, systemctl displays the status of dhcpd and sshd:
$ systemctl status dhcpd.service dhcpd.service - DHCPv4 Server Daemon Loaded: loaded (/lib/systemd/system/dhcpd.service) Active: inactive (dead) CGroup: name=systemd:/system/dhcpd.service $ systemctl status sshd.service sshd.service - LSB: Start up the OpenSSH server daemon Loaded: loaded (/etc/rc.d/init.d/sshd) Active: active (running) since Wed, 20 Apr 2011 19:08:32 -0700; 19h ago Main PID: 817 (sshd) CGroup: name=systemd:/system/sshd.service + 817 /usr/sbin/sshd
The systemctl utility requires a period and unit type (.service in the preceding example) following a unit name (dhcpd and sshd in the preceding example). The lines that start with Loaded name the file controlling each daemon (service). The dhcpd daemon is controlled by /lib/systemd/system/dhcpd.service. The location of the file (the /lib/systemd hierarchy) and its filename extension (.service) indicate systemd is running the daemon natively. The sshd daemon is controlled by /etc/rc.d/init.d/sshd. The location of the file (the init.d directory) and the lack of a filename extension indicate systemd is running the daemon via a SysVinit script. See fedoraproject.org/wiki/User:Johannbg/QA/Systemd/compatability for a list of services that have been ported to systemd (and are run natively by systemd).
You can use service to display the same information as systemctl status. However, service does not accept a period and unit type.
# service dhcpd status dhcpd.service - DHCPv4 Server Daemon Loaded: loaded (/lib/systemd/system/dhcpd.service) Active: inactive (dead) CGroup: name=systemd:/system/dhcpd.service # service sshd status sshd.service - LSB: Start up the OpenSSH server daemon Loaded: loaded (/etc/rc.d/init.d/sshd) Active: active (running) since Wed, 20 Apr 2011 19:08:32 -0700; 19h ago Main PID: 817 (sshd) CGroup: name=systemd:/system/sshd.service + 817 /usr/sbin/sshd
Setting and Changing Runlevels
The runlevel specifies which daemons are running and which interfaces are available on a system. See “Runlevels” and Table 11-1 for more information. This section describes how to set the persistent (default) runlevel (the runlevel the system boots to) and how to change the current runlevel.
Under systemd no true runlevels exist; see “Runlevels” For example, the default runlevel under Fedora is graphical.target and has an alternative name of runlevel5.target. Under SysVinit this runlevel is referred to as runlevel 5 (multiuser graphical mode). The /etc/systemd/system/default.target file is a link to the file that specifies the target the system will boot to by default:
$ ls -l /etc/systemd/system/default.target lrwxrwxrwx. 1 root root 36 04-20 10:07 /etc/systemd/system/default.target -> /lib/systemd/system/runlevel5.target
The following command shows runlevel5.target is a link to graphical.target:
$ ls -l /lib/systemd/system/runlevel5.target lrwxrwxrwx. 1 root root 16 04-08 14:33 /lib/systemd/system/runlevel5.target -> graphical.target
The multi-user.target file (and the link to it, runlevel3.target) causes the system to boot to the multiuser runlevel (multiuser textual mode; SysVinit runlevel 3). The following command replaces the link shown in the previous example and will cause the system enter multiuser textual mode each time it is booted. This command does not change the current runlevel.
# ln -sf /lib/systemd/system/multi-user.target /etc/systemd/system/default.target
The –s (symbolic) option creates a symbolic link, and the –f (force) option overwrites any existing file. After giving the preceding command and rebooting the system, the systemctl list-units command shows the system is in multiuser mode:
$ systemctl list-units --type=target ... multi-user.target loaded active active Multi-User ...
Changing the Current Runlevel
The systemctl isolate command changes the current runlevel of the system. The following command changes the runlevel to multiuser graphical mode (graphical.target). When the system is rebooted, it will return to the default runlevel as specified by the link at /etc/systemd/system/default.target.
# systemctl isolate graphical.target
After a few moments, systemctl shows the system is in the runlevel specified by graphical.target:
$ systemctl list-units --type=target ... graphical.target loaded active active Graphical Interface ...
The preceding examples were run from an ssh login. If you give these commands from a terminal emulator running in a GUI, the system will log you out each time the system changes runlevel.
Configuring Daemons (Services)
Two states are important when you consider a daemon: its current state and its persistent state (the state it will be in after the system is booted). Possible states are running and stopped. Under Fedora, daemons are stopped when they are installed and are set up to be stopped after the system is booted.
The systemctl utility controls the current and persistent states of daemons that run natively under systemd. The service and chkconfig utilities originally controlled daemons that run under SysVinit and were upgraded to control daemons that run under Upstart. Now these utilities have been retrofitted to control daemons that run under systemd, which they do by calling systemctl. You can still use service to control the current state of a daemon and chkconfig to control the persistent state of a daemon.
The next sections describe the systemctl commands that control daemons, followed by the service or chkconfig commands that perform the same functions.
The systemctl disable command causes a daemon not to start when the system is booted. This command has no effect on the current state of the daemon. You must specify the .service part of the service name.
# systemctl disable ntpd.service rm '/etc/systemd/system/multi-user.target.wants/ntpd.service'
The preceding command removes the link that causes systemd to start ntpd when the system enters multi-user runlevel and, by inheritance, graphical runlevel. See “/etc/systemd/system Hierarchy: Controls Services and the Persistent Runlevel” for a discussion of these links.
The preceding command works on the ntpd daemon, which is run natively by systemd. If you run the same command on a daemon controlled by a SysVinit script, such as cups, it calls chkconfig (covered shortly). Even though no cups.service service or file exists, you must specify the .service part of the service name.
# systemctl disable cups.service cups.service is not a native service, redirecting to /sbin/chkconfig. Executing /sbin/chkconfig cups off
The following commands each verify the ntpd daemon will not start when the system boots. The first command shows no links in the .wants directories for ntpd.service. The second uses the systemctl is-enabled, which sets its exit status to 0 (zero) if the service is enabled or to nonzero otherwise. The || Boolean operator executes the echo command if systemctl returns a nonzero exit status (fails).
# ls /etc/systemd/system/.wants/ntpd.service ls: cannot access /etc/systemd/system/.wants/ntpd.service: No such file or directory # systemctl is-enabled ntpd.service || echo ntpd is not enabled ntpd is not enabled
The systemctl enable command causes a daemon to start when the system is booted. This command has no effect on the current state of the daemon. It creates the link that causes systemd to start ntpd when the system enters multiuser textual mode and, by inheritance, multiuser graphical mode. If you run the same command on a daemon that is controlled by a SysVinit script, it calls chkconfig (covered shortly).
# systemctl enable ntpd.service ln -s '/lib/systemd/system/ntpd.service' '/etc/systemd/system/multi-user.target.wants/ntpd.service'
As in the preceding example, the next two commands check whether the daemon will start when the system is booted.
$ ls /etc/systemd/system/.wants/ntpd.service /etc/systemd/system/multi-user.target.wants/ntpd.service $ systemctl is-enabled ntpd.service || echo ntpd is not enabled $
The chkconfig off and on commands correspond to the systemctl disable and enable commands. The messages the commands display when run on daemons systemd controls natively show they call systemctl. Because the chkconfig – –list option does not display the correct information for daemons controlled natively by systemd; you must use the preceding techniques to determine if such a daemon is enabled.
# chkconfig ntpd off Note: Forwarding request to 'systemctl disable ntpd.service'. rm '/etc/systemd/system/multi-user.target.wants/ntpd.service' # chkconfig ntpd on Note: Forwarding request to 'systemctl enable ntpd.service'. ln -s '/lib/systemd/system/ntpd.service' '/etc/systemd/system/multi-user.target.wants/ntpd.service'
The preceding section discussed the systemctl enable command in terms of causing a daemon to start when the system boots. Most of the time this command works that way. However, the systemctl enable command can cause services to start based on various triggers, not just by the system booting.
For example, when bluetooth.service is enabled, it is controlled by the bluetooth device logic, which starts bluetooth.service when a bluetooth device is plugged in. If the bluetooth device is built in to the computer, this distinction is not important. However, if the bluetooth device is attached to a USB dongle, running systemctl enable means that in the future, the bluetooth service will be started as soon as the dongle is plugged in but not before.
In a similar vein, in future releases of Fedora the cupsd daemon will no longer be started when the system boots. Rather, running systemctl enable will only establish a communication socket for cupsd. The cupsd daemon will not start until a process tries to access it (when someone sends a job to the printer).
Changing the Current State of a Daemon
The systemctl stop command immediately stops a daemon from running. This command has no effect on whether the daemon starts when the system is booted. The following command works on the ntpd daemon, which is run natively by systemd. It will also work on a daemon systemd controls via a SysVinit script. You must always specify the .service part of the service name.
# systemctl stop ntpd.service
The preceding command stops the ntpd daemon. It displays no output, even if you mistype the name of the daemon. The following commands each verify the ntpd daemon is not running.
# systemctl status ntpd.service ntpd.service - Network Time Service Loaded: loaded (/lib/systemd/system/ntpd.service) Active: inactive (dead) since Fri, 22 Apr 2011 08:50:59 -0700; 17ms ago Process: 1036 ExecStart=/usr/sbin/ntpd -n -u ntp:ntp $OPTIONS (code=exited, status=0/SUCCESS) CGroup: name=systemd:/system/ntpd.service # systemctl is-active ntpd.service inactive
The systemctl status command shows an Active status of inactive (dead). The systemctl is-active command displays a status of inactive. You can also use ps –ef | grep ntpd to determine if the daemon is running.
The systemctl start command immediately starts a daemon running. This command has no effect on whether the daemon starts when the system is booted.
# systemctl start ntpd.service
The next two commands each show the daemon is running.
# systemctl status ntpd.service ntpd.service - Network Time Service Loaded: loaded (/lib/systemd/system/ntpd.service) Active: active (running) since Fri, 22 Apr 2011 08:50:59 -0700; 33ms ago Main PID: 1562 (ntpd) CGroup: name=systemd:/system/ntpd.service + 1562 /usr/sbin/ntpd -n -u ntp:ntp -g # systemctl is-active ntpd.service active
The service stop, start, and status commands correspond the systemctl stop, start, and status commands. The messages the stop and start commands display show they simply call systemctl. You can use the service status command (or the systemctl status command) to display the status of a daemon.
# service ntpd stop Stopping ntpd (via systemctl): [ OK ] # service ntpd start Starting ntpd (via systemctl): [ OK ] # service ntpd status ntpd.service - Network Time Service Loaded: loaded (/lib/systemd/system/ntpd.service) Active: active (running) since Fri, 22 Apr 2011 08:50:59 -0700; 102ms ago Main PID: 1615 (ntpd) CGroup: name=systemd:/system/ntpd.service + 1615 /usr/sbin/ntpd -n -u ntp:ntp -g
This excerpt is from the new 6th edition of the book, ‘A Practical Guide to Fedora and Red Hat Enterprise Linux’ by Mark G. Sobell, published by Pearson/Prentice Hall Professional, Aug. 2011, ISBN 0132757273, Copyright 2012 Mark G. Sobell. For more info, please visit http://sobell.com or the publisher site: www.informit.com/title/0132757273