systemd

systemd

systemd is a suite providing a system and service manager that runs as PID 1 and starts the rest of the system.
This powerful suite of software can manage many aspects of your server, from services to mounted devices and system states.

Understanding Systemd Units and Unit Files

In systemd, a unit refers to any resource that the system knows how to operate on and manage. This is the primary object that the systemd tools know how to deal with. These resources are defined using configuration files called unit files.

Units in some ways can be said to similar to services or jobs in other init systems. Unit files are loaded from multiple locations, to see the full list, run


$ systemctl show --property=UnitPath
UnitPath=/etc/systemd/system.control /run/systemd/system.control /run/systemd/transient /run/systemd/generator.early 
/etc/systemd/system /etc/systemd/system.attached /run/systemd/system /run/systemd/system.attached /run/systemd/generator 
/usr/local/lib/systemd/system /lib/systemd/system /usr/lib/systemd/system /run/systemd/generator.late
but the main ones are
  • /etc/systemd/system/
  • Units installed by the system administrator.
    Unit files found in this directory location take precedence over any of the other locations on the filesystem
  • /usr/lib/systemd/system/
  • Units provided by installed packages.
  • /run/systemd/system
  • Unit files found in this directory are for dynamically created unit files at runtime.
    All changes made in this directory will be lost when the server is rebooted.
A unit file is a plain text ini-style file that encodes information about a service, a socket, a device, a mount point, an automount point, a swap file or partition, a start-up target, a watched file system path, or a timer .
Unit files are controlled and supervised by systemd.

Types of Units

Systemd categories units according to the type of resource they describe.
The easiest way to determine the type of a unit is with its type suffix, which is appended to the end of the resource name.
  • .service
  • A system service.
  • .socket
  • An inter-process communication socket.
    At boot time, systemd creates listening sockets for all system services that support this type of activation, and passes the sockets to these services as soon as they are started.
  • .device
  • A device file recognized by the kernel.
    System services that support device-based activation can be started on-demand when a particular type of hardware is plugged in or becomes available.
  • .mount
  • A file system mount point.
    Systemd monitors and manages mount points.
  • .automount
  • A file system automount point.
    Systemd monitors and manages automount points.
  • .swap
  • A swap device or a swap file.
  • .target
  • A group of systemd units.
  • .path
  • A file or directory in a file system.
    System services that support path-based activation can be started on-demand when a particular file or directory changes its state.
  • .timer
  • A systemd timer.
  • .snapshot
  • A saved state of the systemd manager.
  • .slice
  • A group of hierarchically organized units that manage system processes by cgroup.
  • .scope
  • This is created programmatically using the bus interfaces of systemd to manages a set of system processes.
Many of the unit types work together to add functionality.
For instance, some units are used to trigger other units and provide activation functionality.
Their inter-dependencies are specified by the directives "Wants=", "Requires=", "Before=", "After=", ....

Handling dependencies

With systemd, dependencies can be resolved by designing the unit files correctly.
The most typical case is that the unit A requires the unit B to be running before A is started.
In that case add Requires=B and After=B to the [Unit] section of A.
If the dependency is optional, add Wants=B and After=B instead.

Note that Wants= and Requires= do not imply After=, meaning that if After= is not specified, the two units will be started in parallel. Dependencies are typically placed on services and not on #Targets. For example, network.target is pulled in by whatever service configures your network interfaces, therefore ordering your custom unit after it is sufficient since network.target is started anyway.

Writing unit files (Understanding the Unit File Structure)

Unit file names take the following form:

unit_name.unit_type
The internal structure of unit files are organized with sections.
Sections are denoted by a pair of square brackets “[” and “]” with the section name enclosed within.
Section names are well defined and case-sensitive.
A unit file contains directives that describe the unit and define its behavior.
Within these sections, directives are defined through the use of a directive=value format.
For ex., /usr/lib/systemd/user/dbus.service:

[Unit]
Description=D-Bus User Message Bus
Documentation=man:dbus-daemon(1)
Requires=dbus.socket

[Service]
ExecStart=/usr/bin/dbus-daemon --session --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
ExecReload=/usr/bin/dbus-send --print-reply --session --type=method_call --dest=org.freedesktop.DBus / org.freedesktop.DBus.ReloadConfig

Unit files typically consist of several sections.
The common configuration items are configured in the generic [Unit] and [Install] sections.
  • [Unit]
  • This is generally used for defining metadata for the unit and configuring the relationship of the unit to other units.
    Some common directives that you will find in the [Unit] section are:
    • Description
    • This directive can be used to describe the name and basic functionality of the unit. This text is displayed in the output of the systemctl status command.
    • Documentation
    • Provides a list of URIs referencing documentation for the unit.
    • Requires
    • This directive lists any units upon which this unit essentially depends. If the current unit is activated, the units listed here must successfully activate as well, else this unit will fail. These units are started in parallel with the current unit by default.
    • Wants
    • This directive is similar to Requires, but less strict.
      Systemd will attempt to start any units listed here when this unit is activated. If these units are not found or fail to start, the current unit will continue to function.
    • Before
    • The unit starts only before the units specified in Before are active.
    • After
    • The unit starts only after the units specified in After are active. Unlike Requires, After does not explicitly activate the specified units.
    • Conflicts
    • This can be used to list units that cannot be run at the same time as the current unit.
  • [Install]
  • This contains information about unit installation used by systemctl enable and disable commands.
    • Alias
    • Provides a space-separated list of additional names for the unit.
    • RequiredBy
    • A list of units that depend on the unit. When this unit is enabled, the units listed in RequiredBy gain a Require dependency on the unit.
    • WantedBy
    • A list of units that weakly depend on the unit. When this unit is enabled, the units listed in WantedBy gain a Want dependency on the unit.
    • Also
    • Specifies a list of units to be installed or uninstalled along with the unit.
    • DefaultInstance
    • In template unit files, this specifies for which instance the unit shall be enabled if the template is enabled without any explicitly set instance.
  • [Service]
  • The [Service] section is used to provide configuration that is only applicable for services. Some commonly used directives:
    • Type
    • This categorizes services by their process and daemonizing behavior. This affects the functionality of ExecStart and related options. The Type= directive can be one of the following:
      • simple
      • The default value. The process started with ExecStart is the main process of the service.
      • forking
      • The process started with ExecStart spawns a child process that becomes the main process of the service. The parent process exits when the startup is complete.
      • oneshot
      • This type is similar to simple, but systemd should wait for the process to exit before continuing on with other units.
      • dbus
      • This type is similar to simple, but consequent units are started only after the main process gains a D-Bus name.
      • notify
      • This indicates that the service will issue a notification when it has finished starting up. The systemd process will wait for this to happen before proceeding to other units.
      • idle
    • ExecStart
    • Specifies commands or scripts to be executed when the unit is started. If the path to the command is preceded by a dash “-” character, non-zero exit statuses will be accepted without marking the unit activation as failed.
    • ExecStop
    • Specifies commands or scripts to be executed when the unit is stopped.
    • ExecReload
    • Specifies commands or scripts to be executed when the unit is reloaded.
    • Restart
    • With this option enabled, the service is restarted after its process exits, with the exception of a clean stop by the systemctl command.
      This can be set to values like “always”, “on-success”, “on-failure”, “on-abnormal”, “on-abort”, or “on-watchdog”. These will trigger a restart according to the way that the service was stopped.
  • [Socket]
  • .socket files must include a [Socket] section, which carries information about the socket or FIFO it supervises.
    • ListenStream
    • ListenDatagram
    • ListenSequentialPacket
    • Specifies an address to listen on for a stream (SOCK_STREAM), datagram (SOCK_DGRAM), or sequential packet (SOCK_SEQPACKET) socket, respectively.
      The address can be written in various formats.
    • ListenFIFO
    • Specifies a file system FIFO to listen on. This expects an absolute file system path as argument.
    • Accept
    • If true, a service instance is spawned for each incoming connection and only the connection socket is passed to it.
    • SocketMode
    • If listening on a file system socket or FIFO, this option specifies the file system access mode used when creating the file node. . Defaults to 0666.
    • Service
    • If the service name does not match the .socket name, the service can be specified with this directive. This setting is only allowed for sockets with Accept=no.
    • SocketUser
    • SocketGroup
    • Takes a UNIX user/group name. When specified, all AF_UNIX sockets and FIFO nodes in the file system are owned by the specified user and group.
      If unset (the default), the nodes are owned by the root user/group.
  • [Mount]
  • The mount specific configuration options are configured in the [Mount] section, which carries information about the file system mount points it supervises.
    Mounts listed in /etc/fstab will be converted into native units dynamically at boot. Mount points created at runtime will be monitored by systemd.
    When reading /etc/fstab a few special mount options are understood by systemd which influence how dependencies are created for mount points.
    Mount points are named after the directory that they control, with a translation algorithm applied: the leading slash is removed, all other slashes are translated into dashes “-”, and all dashes and unprintable characters are replaced with C-style escape codes.
    
    $ cat /etc/fstab
    # <file system>                           <mount point>   <type>  <options>       <dump>  <pass>
    # / was on /dev/sdb5 during installation
    UUID=b914dd46-1239-455a-b372-f54b504ca98d       /               ext4    errors=remount-ro 0       1
    # /boot/efi was on /dev/sda3 during installation
    UUID=5ECD-C227                                  /boot/efi       vfat    umask=0077      0       1
    /swapfile                                       none            swap    sw              0       0
    
    
    $ tree /run/systemd/generator/
    /run/systemd/generator/
    ├── boot-efi.mount
    ├── local-fs.target.requires
    │   ├── boot-efi.mount -> ../boot-efi.mount
    │   └── -.mount -> ../-.mount
    ├── local-fs.target.wants
    │   └── systemd-fsck-root.service -> /lib/systemd/system/systemd-fsck-root.service
    ├── -.mount
    ├── netplan.stamp
    ├── swapfile.swap
    └── swap.target.requires
        └── swapfile.swap -> ../swapfile.swap        
    
    $ cat /run/systemd/generator/-.mount
    # Automatically generated by systemd-fstab-generator
    
    [Unit]
    SourcePath=/etc/fstab
    Documentation=man:fstab(5) man:systemd-fstab-generator(8)
    Before=local-fs.target
    
    [Mount]
    Where=/
    What=/dev/disk/by-uuid/b914dd46-1239-455a-b372-f54b504ca98d
    Type=ext4
    Options=errors=remount-ro
    
    $ systemctl status boot-efi.mount
    ● boot-efi.mount - /boot/efi
       Loaded: loaded (/etc/fstab; generated)
       Active: active (mounted) since Sun 2020-10-11 09:42:11 CST; 5h 6min ago
        Where: /boot/efi
         What: /dev/sda3
         Docs: man:fstab(5)
               man:systemd-fstab-generator(8)
      Process: 652 ExecMount=/bin/mount /dev/disk/by-uuid/5ECD-C227 /boot/efi -t vfat -o umask=0077 (code=exited,
        Tasks: 0 (limit: 4915)
       CGroup: /system.slice/boot-efi.mount
            
            
    The options specific to the [Mount] section of mount units are the following:
    • What
    • The absolute path (a device node, file or other resource) to the resource that needs to be mounted.
    • Where
    • The absolute path of the mount point where the resource should be mounted. This should be the same as the unit file name, except using conventional filesystem notation.
    • Type
    • The filesystem type of the mount.
    • Options
    • Any mount options that need to be applied. This is a comma-separated list.
    • SloppyOptions
    • A boolean that determines whether the mount will fail if there is an unrecognized mount option. Defaults to off.
    • DirectoryMode
    • Directories of mount points (and any parent directories) are automatically created if needed. Defaults to 0755.
    • TimeoutSec
    • Configures the amount of time the system will wait until the mount operation is marked as failed.
  • [Automount]
  • Automount units may be used to implement on-demand mounting as well as parallelized mounting of file systems.
    For each automount unit file a matching mount unit file must exist which is activated when the automount path is accessed.
    Automount files must include an [Automount] section, the options specific to the [Automount] section
    • Where
    • The absolute path of the automount point on the filesystem. This string must be reflected in the unit filename.
      Example: the automount point /home/lennart must be configured in a unit file home-lennart.automount.
    • DirectoryMode
    • If the automount point or any parent directories need to be created, this will determine the permissions settings of those path components.
  • [Swap]
  • Swap units must be named after the devices or files they control.
    Example: the swap device /dev/sda5 must be configured in a unit file dev-sda5.swap.
    Like the mount options, the swap units can be automatically created from /etc/fstab entries, or can be configured through a dedicated unit file.
    
    $ cat /run/systemd/generator/swapfile.swap
    # Automatically generated by systemd-fstab-generator
    
    # Automatically generated by systemd-fstab-generator
    
    [Unit]
    SourcePath=/etc/fstab
    Documentation=man:fstab(5) man:systemd-fstab-generator(8)
    
    [Swap]
    What=/swapfile
    Options=sw
      	
    If a swap device or file is configured in both /etc/fstab and a unit file, the configuration in the latter takes precedence.
    • What
    • The absolute path to the location of the swap space, whether this is a file or a device.
    • Priority
    • This takes an integer that indicates the priority of the swap being configured.
    • Options
    • Any options that are typically set in the /etc/fstab file can be set with this directive instead. A comma-separated list is used.
    • TimeoutSec
    • The amount of time that systemd waits for the swap to be activated before marking the operation as a failure.
  • [Path]
  • A path unit defines a filesystem path that systmed can monitor for changes.
    Another unit must exist that will be be activated when certain activity is detected at the path location. Path activity is determined thorugh inotify events.
    • PathExists
    • This directive is used to check whether the path in question exists. If it does, the associated unit is activated.
    • PathExistsGlob
    • This is the same as the above, but checks for the existence of at least one file matching the globbing pattern specified.
    • PathChanged
    • Watch a file or directory and activate the configured unit whenever it changes.
    • PathModified
    • This watches for changes like the above directive, but it activates on file writes as well as when the file is closed.
    • DirectoryNotEmpty
    • This directive allows systemd to activate the associated unit when the directory is no longer empty.
    • Unit
    • This specifies the unit to activate when the path conditions specified above are met. The argument is a unit name, whose suffix is not ".path".
    • MakeDirectory
    • This determines if systemd will create the directory structure of the path in question prior to watching.
    • DirectoryMode
    • If the above is enabled, this will set the permission mode of any path components that must be created.
  • [Timer]
  • Timer units are used to schedule tasks to operate at a specific time or after a certain delay. (similar to the cron and at daemons)
    An associated unit must be provided which will be activated when the timer is reached.
    • OnActiveSec
    • Defines a timer relative to the moment the timer unit itself is activated.
    • OnBootSec
    • Defines a timer relative to when the machine was booted up.
    • OnStartupSec
    • Defines a timer relative to when the systemd was first started.
    • OnUnitActiveSec
    • This sets a timer according to when the associated unit was last activated.
    • OnUnitInactiveSec
    • This sets the timer in relation to when the associated unit was last marked as inactive.
    • OnCalendar
    • This allows you to activate the associated unit by specifying an absolute realtime (i.e. wallclock) instead of relative to an event.
    • AccuracySec
    • Specify the accuracy the timer shall elapse with. Defaults to 1min.
    • Unit
    • This directive is used to specify the unit that should be activated when the timer elapses.
    • Persistent
    • WakeSystem
  • [Slice]
  • A slice unit is a concept for hierarchically managing resources of a group of processes. This management is performed by creating a node in the Linux Control Group (cgroup) tree.
    Systemd uses cgroups to organise processes:
    • each service is a cgroup
    • all processes started by that service use that cgroup
    With cgroup, systemd handles blkio, cpu, device, and memory accounting for you.
    The system’s resources get divided up into slices.
    Units that manage processes (primarily scope and service units) may be assigned to a specific slice.
    There are 4 ".slice" units which form the basis of the hierarchy for assignment of resources for services, users, and virtual machines or containers:
    • -.slice
    • The root slice is the root of the slice hierarchy. It usually does not contain units directly, but may be used to set defaults for the whole tree.
    • system.slice
    • By default, all system services started by systemd are found in this slice.
    • user.slice
    • By default, all user processes and services started on behalf of the user, including the per-user systemd instance are found in this slice. This is pulled in by systemd-logind.service.
    • machine.slice
    • By default, all virtual machines and containers registered with systemd-machined are found in this slice. This is pulled in by systemd-machined.service.
    For each slice, certain resource limits may be set that apply to all processes of all units contained in that slice.
    Slices are organized hierarchically in a tree. The name of the slice consists of a dash-separated series of names, which describes the path to the slice from the root slice. The root slice is named -.slice.
    For ex.,
    • user-1000.slice is a slice that is located within user.slice
    • user.slice located in the root slice -.slice.
    
    $ systemd-cgls | grep slice
    -.slice
    ├─user.slice
    │ ├─user-1000.slice
    │ │ │ │ └─4612 grep --color=auto slice
    │ └─user-121.slice
    └─system.slice
            
            
    The [Slice] section of a unit file actually does not have any .slice unit specific configuration.

Creating Instance Units from Template Unit Files

Template unit files can be identified because they contain an @ symbol after the base unit name and before the unit type suffix.
For ex.,

example@.service
When an instance is created from a template, an instance identifier is placed between the @ symbol and the period signifying the start of the unit type.

│ ├─user-1000.slice
│ │ ├─user@1000.service

An instance file is usually created as a symbolic link to the template file, with the link name including the instance identifier. In this way, multiple links with unique identifiers can point back to a single template file.
The following are some of the more common specifiers will be replaced when an instance unit is interpreted with the relevant information:
  • %n
  • Anywhere where this appears in a template file, the full resulting unit name will be inserted.
  • %N
  • This is the same as the above, but any escaping, such as those present in file path patterns, will be reversed.
  • %p
  • This references the unit name prefix. This is the portion of the unit name that comes before the @ symbol.
  • %P
  • This is the same as above, but with any escaping reversed.
  • %i
  • This references the instance name, which is the identifier following the @ in the instance unit. This is one of the most commonly used specifiers because it will be guaranteed to be dynamic. The use of this identifier encourages the use of configuration significant identifiers. For example, the port that the service will be run at can be used as the instance identifier and the template can use this specifier to set up the port specification.
  • %I
  • This specifier is the same as the above, but with any escaping reversed.
  • %f
  • This will be replaced with the unescaped instance name or the prefix name, prepended with a /.
  • %c
  • This will indicate the control group of the unit, with the standard parent hierarchy of /sys/fs/cgroup/ssytemd/ removed.
  • %u
  • The name of the user configured to run the unit.
  • %U
  • The same as above, but as a numeric UID instead of name.
  • %H
  • The host name of the system that is running the unit.
  • %%
  • This is used to insert a literal percentage sign.

Creating Custom Unit Files

The following procedure describes the general process of creating a custom service:
  1. Prepare the executable file with the custom service.
  2. This can be a custom-created script, or an executable delivered by a software provider. If required, prepare a PID file to hold a constant PID for the main process of the custom service. It is also possible to include environment files to store shell variables for the service. Make sure the source script is executable (by executing the chmod a+x) and is not interactive.
  3. Create a unit file in the /etc/systemd/system/ directory and make sure it has correct file permissions.
  4. Execute as root:
    
    		touch /etc/systemd/system/name.service
    		chmod 664 /etc/systemd/system/name.service
    	
  5. Add configuration options to the name.service file
  6. An example unit configuration for a network-related service:
    
    [Unit]
    Description=service_description
    After=network.target
    
    [Service]
    ExecStart=path_to_executable
    Type=forking
    PIDFile=path_to_pidfile
    
    [Install]
    WantedBy=default.target    
        
    where:
    • the After setting ensures that the service is started only after the network is running. Add a space-separated list of other relevant services or targets.
    • WantedBy states the target or targets that the service should be started under.
    • Think of these targets as of a replacement of the older concept of sysv init's runlevels,
  7. Notify systemd that a new name.service file exists
  8. 
    systemctl daemon-reload
    systemctl start name.service    	
         
    Always run the systemctl daemon-reload command after creating new unit files or modifying existing unit files. Otherwise, the systemctl start or systemctl enable commands could fail due to a mismatch between states of systemd and actual service unit files on disk.

Modifying Existing Unit Files

Services installed on the system come with default unit files that are stored in the /usr/lib/systemd/ directory. System Administrators should not modify these files directly.
Any customization must be confined to configuration files in the /etc/systemd/system/ directory.
Depending on the extent of the required changes, pick one of the following approaches to change /etc/systemd/system/:
  • Create a directory for supplementary configuration files under /etc/systemd/system/
  • Create a copy of the original unit file /usr/lib/systemd/system/ in /etc/systemd/system/ and make changes there.
With this, in order to return to the default configuration of the unit, just delete custom-created configuration files in /etc/systemd/system/.
The configuration files from configuration directories in /etc/systemd/system/ take precedence over unit files in /usr/lib/systemd/.
To display an overview of overridden or modified unit files,

$ systemd-delta
[EXTENDED]   /lib/systemd/system/rc-local.service → /lib/systemd/system/rc-local.service.d/debian.conf
[EXTENDED]   /lib/systemd/system/user@.service → /lib/systemd/system/user@.service.d/timeout.conf

2 overridden configuration files found.

systemd/User

There is one system-wide instance of systemd. It always runs. Only an administrator has the authority to control system services.
systemd offers users the ability to manage services under the user's control with a per-user systemd instance, enabling users to start, stop, enable, and disable their own units.
There are multiple per-user instances of systemd. They are started/stopped on demand. Only that user (or an administrator) has the authority to control his own services.
This is convenient for daemons and other services that are commonly run for a single user, or to perform automated tasks like fetching mail.
When a user session starts (either remotely via ssh or local), an instance of systemd --user starts for that user.
The instance of systemd --user is started automatically at login provided that the pam_systemd module is active in pam for the requested session.
pam_systemd registers user sessions with the systemd login manager systemd-logind.service, and hence the systemd control group hierarchy:
  1. If it does not exist yet, the user runtime directory /run/user/$UID is either created or mounted as new "tmpfs" file system with quota applied, and its ownership changed to the user that is logging in.
  2. The $XDG_SESSION_ID environment variable is initialized. If auditing is available and pam_loginuid.so was run before this module (which is highly recommended), the variable is initialized from the auditing session id (/proc/self/sessionid). Otherwise, an independent session counter is used.
  3. A new systemd scope unit is created for the session. If this is the first concurrent session of the user, an implicit per-user slice unit below user.slice is automatically created and the scope placed into it. An instance of the system service user@.service, which runs the systemd user manager instance, is started.
  4. The "$TZ", "$EMAIL" and "$LANG" environment variables are configured for the user, based on the respective data from the user's JSON record (if it is defined). Moreover, any environment variables explicitly configured in the user record are imported, and the umask, nice level, and resource limits initialized.

Systemd init

Linux system is started by the systemd program with PID=1 (i.e., init process).
The systemd init process spawns processes in parallel based on the unit configuration files which are written in declarative style instead of SysV-like procedural style.
Upon system start up (i.e., init), the systemd process tries to start the "/lib/systemd/system/default.target (normally symlinked to "graphical.target").

[Unit]
Description=Graphical Interface
Documentation=man:systemd.special(7)
Requires=multi-user.target
Wants=display-manager.service
Conflicts=rescue.service rescue.target
After=multi-user.target rescue.service rescue.target display-manager.service
AllowIsolate=yes

systemd offers backward compatibility features. SysV-style boot scripts in "/etc/init.d/rc[0123456S].d/[KS]<name>" are still parsed
  • multi-user.target
  • 
    [Unit]
    Description=Multi-User System
    Documentation=man:systemd.special(7)
    Requires=basic.target
    Conflicts=rescue.service rescue.target
    After=basic.target rescue.service rescue.target
    AllowIsolate=yes    
        
    • basic.target
    • 
      [Unit]
      Description=Basic System
      Documentation=man:systemd.special(7)
      Requires=sysinit.target
      Wants=sockets.target timers.target paths.target slices.target
      After=sysinit.target sockets.target paths.target slices.target tmp.mount
      RequiresMountsFor=/var /var/tmp
      Wants=tmp.mount        
              
      • sysinit.target
      • 
        [Unit]
        Description=System Initialization
        Documentation=man:systemd.special(7)
        Conflicts=emergency.service emergency.target
        Wants=local-fs.target swap.target
        After=local-fs.target swap.target emergency.service emergency.target        
                    
        • local-fs.target
        • 
          [Unit]
          Description=Local File Systems
          Documentation=man:systemd.special(7)
          DefaultDependencies=no
          Conflicts=shutdown.target
          After=local-fs-pre.target
          OnFailure=emergency.target
          OnFailureJobMode=replace-irreversibly                
                          
          • local-fs-pre.target
          • 
            [Unit]
            Description=Local File Systems (Pre)
            Documentation=man:systemd.special(7)
            RefuseManualStart=yes                    
                                
        • swap.target
        • 
          [Unit]
          Description=Swap
          Documentation=man:systemd.special(7)                
                          
        • emergency.service
        • 
          [Unit]
          Description=Emergency Shell
          Documentation=man:sulogin(8)
          DefaultDependencies=no
          Conflicts=shutdown.target
          Conflicts=rescue.service
          Before=shutdown.target
          Before=rescue.service
          
          [Service]
          Environment=HOME=/root
          WorkingDirectory=-/root
          ExecStartPre=-/bin/plymouth --wait quit
          ExecStart=-/lib/systemd/systemd-sulogin-shell emergency
          Type=idle
          StandardInput=tty-force
          StandardOutput=inherit
          StandardError=inherit
          KillMode=process
          IgnoreSIGPIPE=no
          SendSIGHUP=yes
                          
                          
        • emergency.target
        • 
          [Unit]
          Description=Emergency Mode
          Documentation=man:systemd.special(7)
          Requires=emergency.service
          After=emergency.service
          AllowIsolate=yes                
                          
      • sockets.target
      • 
        [Unit]
        Description=Sockets
        Documentation=man:systemd.special(7)            
                    
      • paths.target
      • 
        [Unit]
        Description=Paths
        Documentation=man:systemd.special(7)            
                    
      • slices.target
      • 
        [Unit]
        Description=Slices
        Documentation=man:systemd.special(7)
        Wants=-.slice system.slice
        After=-.slice system.slice          
                    
        • -.slice
        • 
                          
                          
        • system.slice
        • 
          [Unit]
          Description=System Slice
          Documentation=man:systemd.special(7)
          DefaultDependencies=no
          Before=slices.target                
                          
      • tmp.mount
    • rescue.service
    • rescue.target

Examples

Creating the hello.service File

  1. Create a hello daemon application
  2. sudo vi /usr/bin/hello:
    
    #!/bin/bash
    
    x=1
    
    while [ $x -le 5 ]
    do
      logger "Welcome $x times"
      x=$(( $x + 1 ))
      sleep 60
    done       
        
  3. Create a unit file in the /etc/systemd/system/ directory and make sure it has the correct file permissions. Execute as root
  4. sudo vi /etc/systemd/system/hello.service ,
    
    [Unit]
    Description=Hello: just say hi
    
    [Service]
    Type=simple
    ExecStart=/usr/bin/hello
    
    [Install]
    WantedBy=default.target    
        
  5. Execute the following commands to reload the configuration and start the custom service
  6. 
    sudo systemctl daemon-reload
    sudo systemctl start hello.service
        
As the hello daemon is now registered as a systemd service, you can use all standard systemctl commands. For example,
  • run systemctl status hello to display the editor’s status
  • run systemctl enable hello to make the hello daemon start automatically on system boot.

Basic systemctl usage

systemctl may be used to investigate and control the state of the "systemd" system and service manager. You can use all of the following systemctl commands with the -H user@host switch to control a systemd instance on a remote machine. This will use SSH to connect to the remote systemd instance.

Analyzing the system state

  • Show system status
  • 
        systemctl status
        
  • List running units
  • 
        systemctl
        
  • List failed units
  • 
        systemctl --failed
        
  • List installed unit files
  • 
        systemctl list-unit-files
        
    The available unit files can be seen in /etc/systemd/system/.
    • List type of unit files
    • 
              $ systemctl list-unit-files --type=service
              
    • list mount files
    • 
              $ systemctl list-unit-files --type=mount 
              
    • list enabled services
    • 
              $ systemctl list-unit-files --type=service --state=enabled
              
    • list running services
    • 
              $ systemctl list-units --type=service --state=running
              
    • Check service status of individual unit file
    • To check if a systemctl service is running or not :
      
              $ systemctl show sshd --property=SubState
      		SubState=running
              
      To check if a service is active or inactive:
      
              $ systemctl show sshd --property=ActiveState
              
    • To list all the properties of a service
    • 
              $ systemctl show sshd
              

How to Change the target (runlevel) in Systemd

The relationship between runlevels numbers and targets.
  • Run level 0
  • is matched by poweroff.target (and runlevel0.target is a symbolic link to poweroff.target).
  • Run level 1
  • is matched by rescue.target (and runlevel1.target is a symbolic link to rescue.target).
  • Run level 3
  • is emulated by multi-user.target (and runlevel3.target is a symbolic link to multi-user.target).
  • Run level 5
  • is emulated by graphical.target (and runlevel5.target is a symbolic link to graphical.target).
  • Run level 6
  • is emulated by reboot.target (and runlevel6.target is a symbolic link to reboot.target).
  • Emergency
  • is matched by emergency.target.
When the system boots, by default systemd activates the default.target unit.
To view the default target,

$ systemctl get-default
graphical.target
To set the default target,

$ systemctl set-default multi-user.target
While the system is running, you can switch the target (run level).
To switch to runlevel 3,

$ systemctl isolate multi-user.target 
The default target unit is represented by the /usr/lib/systemd/system/default.target file.

$ ls -l /usr/lib/systemd/system/default.target
lrwxrwxrwx 1 root root 16 Dec 10 17:04 /usr/lib/systemd/system/default.target -> graphical.target
A list of the targets and services on which a specified target is dependent cab be observed:

$ systemctl list-dependencies sysinit.target

Debug systemd

It's the boot loader or the firmware that loads both the kernel and initrd/initramfs images into memory, but the kernel which interprets it as a file system.
systemd(1) may be used to manage services in the initrd, similarly to the real system.

After the root file system is found and mounted, the initrd hands over control to the host's system manager (such as systemd(1)) stored in the root file system, which is then responsible for probing all remaining hardware, mounting all necessary file systems and spawning all configured services.

systemd initialize the required file systems, services and drivers that are necessary for operation of the system.
This process is split up in various discrete steps which are exposed as target units.

When systemd starts up the system, it will activate all units that are dependencies of default.target.
Usually, default.target is simply an alias of graphical.target or multi-user.target, depending on whether the system is configured for a graphical UI or only for a text console.


                                                cryptsetup-pre.target
                                                             |
           (various low-level                                v
            API VFS mounts:                 (various cryptsetup devices...)
            mqueue, configfs,                                |    |
            debugfs, ...)                                    v    |
            |                                  cryptsetup.target  |
            |  (various swap                                 |    |    remote-fs-pre.target
            |   devices...)                                  |    |     |        |
            |    |                                           |    |     |        v
            |    v                       local-fs-pre.target |    |     |  (network file systems)
            |  swap.target                       |           |    v     v                 |
            |    |                               v           |  remote-cryptsetup.target  |
            |    |  (various low-level  (various mounts and  |             |              |
            |    |   services: udevd,    fsck services...)   |             |    remote-fs.target
            |    |   tmpfiles, random            |           |             |             /
            |    |   seed, sysctl, ...)          v           |             |            /
            |    |      |                 local-fs.target    |             |           /
            |    |      |                        |           |             |          /
            \____|______|_______________   ______|___________/             |         /
                                        \ /                                |        /
                                         v                                 |       /
                                  sysinit.target                           |      /
                                         |                                 |     /
                  ______________________/|\_____________________           |    /
                 /              |        |      |               \          |   /
                 |              |        |      |               |          |  /
                 v              v        |      v               |          | /
            (various       (various      |  (various            |          |/
             timers...)      paths...)   |   sockets...)        |          |
                 |              |        |      |               |          |
                 v              v        |      v               |          |
           timers.target  paths.target   |  sockets.target      |          |
                 |              |        |      |               v          |
                 v              \_______ | _____/         rescue.service   |
                                        \|/                     |          |
                                         v                      v          |
                                     basic.target         rescue.target    |
                                         |                                 |
                                 ________v____________________             |
                                /              |              \            |
                                |              |              |            |
                                v              v              v            |
                            display-    (various system   (various system  |
                        manager.service     services        services)      |
                                |         required for        |            |
                                |        graphical UIs)       v            v
                                |              |            multi-user.target
           emergency.service    |              |              |
                   |            \_____________ | _____________/
                   v                          \|/
           emergency.target                    v
                                         graphical.target

BOOTUP IN THE INITIAL RAM DISK (INITRD)

systemd detects that it is run within an initrd by checking for the file /etc/initrd-release.
The default target in the initrd is initrd.target.

To start Ubuntu in Recovery Mode

  • Show the GRUB menu
    • If the GRUB menu is displayed during boot
    • the automatic countdown may be stopped by pressing any key other than the Enter key.
    • If the menu is not normally displayed during boot
    • Hold down the Shift key as the computer attempts to boot to display the GRUB 2 menu.
      If holding the Shift key method does not display the menu pressing the Esc key repeatedly may display the menu.
  • Edit the GRUB menu
  • After the GRUB menu is shown, press the E key to edit that entry's settings.
    • Delete the line that looks something like
    • 
            		set gfxpayload=$linux_gfx_mode
            	
    • Go to the line that starts with linux and delete everything after ro.
    • append the following to the line (after ro)
    • 
              	recovery nomodeset
              
    • Press CTRL-X/F10 to boot with the temporarily changed settings

Rescue mode and Emergency mode

  • rescue mode
  • The rescue mode is equivalent to single user mode in Linux distributions that uses SysV as the default service manager.
    In rescue mode, all local filesystems will be mounted, only some important services will be started.
    However, no normal services (E.g network services) won't be started.
    The rescue mode is helpful in situations where the system can't boot normally.
    Also, we can perform some important rescue operations, such as reset root password, in rescue mode.
    To boot into rescue mode in Ubuntu 20.04 LTS, append the following to the kernel boot parameters:
    
        systemd.unit=rescue.target
        
  • emergency mode
  • In the emergency mode. No services are started, no mount points are mounted, no sockets are established, nothing.
    All you will have is just a raw shell. To boot into emergency mode in Ubuntu 20.04 LTS, append the following to the kernel boot parameters:
    
        systemd.unit=emergency.target
        
You may need to mount the root (/) file system in read/write mode before doing any operations in this mode.

mount -n -o remount,rw /

Systemd Targets

  • sysinit.target
  • 
    [Unit]
    Description=System Initialization
    Documentation=man:systemd.special(7)
    Conflicts=emergency.service emergency.target
    Wants=local-fs.target swap.target
    After=local-fs.target swap.target emergency.service emergency.target
    	
    sysinit.target.wants/
    
    cryptsetup.target            proc-sys-fs-binfmt_misc.automount  systemd-binfmt.service             systemd-modules-load.service        systemd-udev-trigger.service
    dev-hugepages.mount          sys-fs-fuse-connections.mount      systemd-boot-system-token.service  systemd-random-seed.service         systemd-udevd.service
    dev-mqueue.mount             sys-kernel-config.mount            systemd-hwdb-update.service        systemd-sysctl.service              systemd-update-utmp.service
    kmod-static-nodes.service    sys-kernel-debug.mount             systemd-journal-flush.service      systemd-sysusers.service
    plymouth-read-write.service  sys-kernel-tracing.mount           systemd-journald.service           systemd-tmpfiles-setup-dev.service
    plymouth-start.service       systemd-ask-password-console.path  systemd-machine-id-commit.service  systemd-tmpfiles-setup.service 
        	
    Depend:
    
    $ systemctl list-dependencies sysinit.target
    sysinit.target
    * |-apparmor.service
    * |-blk-availability.service
    * |-dev-hugepages.mount
    * |-dev-mqueue.mount
    * |-keyboard-setup.service
    * |-kmod-static-nodes.service
    * |-lvm2-lvmpolld.socket
    * |-lvm2-monitor.service
    * |-plymouth-read-write.service
    * |-plymouth-start.service
    * |-proc-sys-fs-binfmt_misc.automount
    * |-setvtrgb.service
    * |-sys-fs-fuse-connections.mount
    * |-sys-kernel-config.mount
    * |-sys-kernel-debug.mount
    * |-sys-kernel-tracing.mount
    * |-systemd-ask-password-console.path
    * |-systemd-binfmt.service
    * |-systemd-boot-system-token.service
    * |-systemd-hwdb-update.service
    * |-systemd-journal-flush.service
    * |-systemd-journald.service
    * |-systemd-machine-id-commit.service
    * |-systemd-modules-load.service
    * |-systemd-pstore.service
    * |-systemd-random-seed.service
    * |-systemd-sysctl.service
    * |-systemd-sysusers.service
    * |-systemd-timesyncd.service
    * |-systemd-tmpfiles-setup-dev.service
    * |-systemd-tmpfiles-setup.service
    * |-systemd-udev-trigger.service
    * |-systemd-udevd.service
    * |-systemd-update-utmp.service
    * |-cryptsetup.target
    * | `-systemd-cryptsetup@jerry.service
    * |-local-fs.target
    * | |--.mount
    * | |-boot-efi.mount
    * | |-boot.mount
    * | |-home-jerry.mount
    * | |-home-work.mount
    * | |-opt.mount
    * | |-systemd-fsck-root.service
    * | |-systemd-remount-fs.service
    * | |-tmp.mount
    * | |-usr.mount
    * | `-var.mount
    * `-swap.target
    *   `-dev-disk-by\x2duuid-309b71b6\x2de981\x2d43a4\x2d8ce5\x2dbe2fb794918f.swap        
            
    • local-fs.target
    • 
      [Unit]
      Description=Local File Systems
      Documentation=man:systemd.special(7)
      DefaultDependencies=no
      Conflicts=shutdown.target
      After=local-fs-pre.target
      		
      local-fs.target/
      
      * |--.mount
      * |-boot-efi.mount
      * |-boot.mount
      * |-home-jerry.mount
      * |-home-work.mount
      * |-opt.mount
      * |-systemd-fsck-root.service
      * |-systemd-remount-fs.service
      * |-tmp.mount
      * |-usr.mount
      * `-var.mount    
          		
      Depends:
      
      $ systemctl list-dependencies local-fs.target
      local-fs.target
      * |--.mount
      * |-boot-efi.mount
      * |-boot.mount
      * |-home-jerry.mount
      * |-home-work.mount
      * |-opt.mount
      * |-systemd-fsck-root.service
      * |-systemd-remount-fs.service
      * |-tmp.mount
      * |-usr.mount
      * `-var.mount        
              	
      • local-fs-pre.target
      •   
        [Unit]
        Description=Local File Systems (Pre)
        Documentation=man:systemd.special(7)
        RefuseManualStart=yes
        				
    • swap.target
    • 
       [Unit]
      Description=Swap
      Documentation=man:systemd.special(7)   
          	

Systemd Services

  • modules-load.d
  • Configure kernel modules to load at boot.
    systemd-modules-load.service(8) reads files from the following directories which contain kernel modules to load during boot in a static list.
    • /etc/modules-load.d/*.conf
    • /run/modules-load.d/*.conf
    • /usr/lib/modules-load.d/*.conf
    Each configuration file is named in the style of /etc/modules-load.d/program.conf.
    The configuration files should simply contain a list of kernel module names to load, separated by newlines. Empty lines and lines whose first non-whitespace character is # or ; are ignored.
    For ex.,
    
        # Load virtio-net.ko at boot
        virtio-net
        
    Note that it is usually a better idea to rely on the automatic module loading by PCI IDs, USB IDs, DMI IDs or similar triggers encoded in the kernel modules themselves instead of static configuration like this.

systemd-suspend.service

systemd-suspend.service is a system service that is pulled in by suspend.target and is responsible for the actual system suspend.

Immediately before entering system suspend and/or hibernation, systemd-suspend.service (and the other mentioned units, respectively) will run all executables in /usr/lib/systemd/system-sleep/ and pass two arguments to them.

Try with this template below and put your script in /lib/systemd/system-sleep/ with executable bit:


#!/bin/sh

PATH=/sbin:/usr/sbin:/bin:/usr/bin

case "$1" in
    pre)
            #code execution BEFORE sleeping/hibernating/suspending
    ;;
    post)
            #code execution AFTER resuming
    ;;
esac

exit 0
The line where PATH=/sbin:/usr/sbin:/bin:/usr/bin is assigned explicitely is required if you intend to call commands as you would do in terminal command-line.

The first argument will be "pre", the second either "suspend", "hibernate", "hybrid-sleep", or "suspend-then-hibernate" depending on the chosen action.

Understanding systemd at startup on Linux

留言

熱門文章