Friday, December 27, 2013

What Is Systemd and How It Works (Part 2)

Hello everyone,
Today, I continue the systemd discussion, part2. If you haven't read or missed part 1, you can find it in the following link: http://ktaraghi.blogspot.ca/2013/11/what-is-systemd-and-how-it-works-part-1.html.
In part 1, I said and explained that the common configuration items (in unit files) are configured in the generic [Unit] and [Install] sections. Now, I am going to explain the specific configuration options such as [Service], [Socket] in Unit files.

As you know, from part 1, a unit configuration file whose name ends in .service encodes information about a process controlled and supervised by systemd. A good example could be rsyslog.service or httpd.service.The service specific configuration options are configured in the [Service] section (Figure 1).

                                                                               Figure 1

According to man page, the important options specific to the [Service] section of service units are the following:

Type= 
Configures the process start-up type for this service unit. One of simple, forking, oneshot, dbus, notify or idle.
If set to simple, it is expected that the process configured with ExecStart= is the main process of the service. In this mode, as I explained in part 1, if the process offers functionality to other processes on the system, its communication channels should be installed before the daemon is started up (e.g. sockets set up by systemd, via socket activation), as systemd will immediately proceed starting follow-up units.
If set to forking it is expected that the process configured with ExecStart= will call fork() as part of its start-up. The parent process is expected to exit when start-up is complete and all communication channels set up. The child continues to run as the main daemon process. This is the behavior of traditional UNIX daemons. If this setting is used, it is recommended to also use the PIDFile=
option, so that systemd can identify the main process of the daemon. systemd will proceed starting follow-up units as soon as the parent process exits.
Behavior of dbus is similar to simple, however it is expected that the daemon acquires a name on the D-Bus bus, as configured by BusName=. systemd will proceed starting follow-up units after the D-Bus bus name has been acquired.
Behavior of notify is similar to simple, however it is expected that the daemon sends a notification message via sd_notify(3) or an equivalent call when it finished starting up. systemd will proceed starting follow-up units after this notification message has been sent.

PIDFile=
Takes an absolute file name pointing to the PID file of this daemon. Use of this option is recommended for services where Type= is set to forking. systemd will read the PID of the main process of the daemon after start-up of the service.

BusName=
Takes a D-Bus bus name, that this service is reachable as. This option is mandatory for services where Type= is set to dbus.

ExecStart=
Commands with their arguments that are executed when this service is started. The first argument must be an absolute path name. Basic environment variable substitution is supported. Use ${FOO} as part of a word, or as a word of its own on the command line, in which case it will be replaced by the value of the environment variable including all whitespace it contains, resulting in a single argument. Note that this setting does not directly support shell command lines. If shell command lines are to be used they need to be passed explicitly to a shell implementation of some kind. Example:   ExecStart=/bin/sh -c 'dmesg | tac'

ExecStartPre=, ExecStartPost=  
Additional commands that are executed before or after the command in ExecStart=, respectively. Syntax is the same as for ExecStart=

ExecReload=
Commands to execute to trigger a configuration reload in the service.

ExecStop=
Commands to execute to stop the service started via ExecStart=.

TimeoutStartSec=
Time to wait before starting the ExecStart=.

Restart=
Configures whether the service shall be restarted when the service process exits, is killed, or a timeout is reached. Takes one of no, on-success, on-failure, on-abort, or always. If set to no (the default) the service will not be restarted. If set to on-success it will be restarted only when the service process exits cleanly. In this context, a clean exit means an exit code of 0, or one of the signals SIGHUP, SIGINT, SIGTERM, or SIGPIPE. If set to on-failure the service will be restarted when the process exits with an nonzero exit code, is terminated by a signal (including on core dump), when an operation (such as service reload) times out, and when the configured watchdog timeout is triggered.
If set to on-abort the service will be restarted only if the service process exits due to an uncaught signal not specified as a clean exit status. If set to always the service will be restarted regardless whether it exited cleanly or not, got terminated abnormally by a signal or hit a timeout.

PermissionsStartOnly=
Boolean value, if true the permission based options are applied, such as User.

RootDirectoryStartOnly=
Boolean value, if true, the RootDirectory option applies only to the ExecStart option.

Let's see some examples (Figure 2 and 3):

                                                                           Figure 2


                                                                          Figure 3


Now, according to man page, a unit configuration file whose name ends in .socket encodes information about an IPC or network socket or a file system FIFO controlled and supervised by systemd, for socket-based activation. Socket units may be used to implement on-demand starting of services, as well as parallelized starting of services.
For each socket file a matching service file must exist, describing the service to start on incoming
traffic on the socket. Depending on the setting of Accept= (see below), this must either be named like the socket unit, but with the suffix replaced; or it must be a template file named the same way. Example: a socket file foo.socket needs a matching service foo.service if Accept=false is set. If Accept=true is set a service template file foo@.service must exist from which services are instantiated for each incoming connection.

The options specific to the [Socket] section of socket units are the following:

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 (The address can be a port number, path name for a socket device, or IPv4 or IPv6 address and port number):
If the address starts with a slash (/), it is read as file system socket in the AF_UNIX socket family.
If the address starts with an at symbol (@) it is read as abstract namespace socket in the AF_UNIX family. The @ is replaced with a NUL character before binding.
If the address string is a single number it is read as port number to listen on via IPv6. Depending on the value of BindIPv6Only=  this might result in the service being available via both IPv6 and IPv4 (default) or just via IPv6.
If the address string is a string in the format v.w.x.y:z it is read as IPv4 specifier for listening on an address v.w.x.y on a port z.

Accept=
Takes a boolean argument. If true, a service instance is spawned for each incoming connection and only the connection socket is passed to it. If false, all listening sockets themselves are passed to the started service unit, and only one service unit is spawned for all connections.
 
MaxConnections=
The maximum number of connections to simultaneously run services instances for, when Accept=true is set. If more concurrent connections are coming in, they will be refused until at least one existing connection is terminated. This setting has no effect for sockets configured with Accept=false or datagram sockets. Defaults to 64.

Service= Specifies the service unit name to activate on incoming traffic. This defaults to the service that bears the same name as the socket.

Let's see an example (Figure 4 and 5):

                                                                              Figure 4

                                                                             Figure 5

And that's it for today. In part 3, I will continue and talk about Template unit files and special targets in systemd. Don't miss it.
Thanks all,
Khosro Taraghi