Home Service management
Post
Cancel

Service management

In this article, we will take a look at how service management is used in Linux, first by defining it, understanding its behavior and configuration, and some useful commands.

Note: Im running a CentOS9 Stream in this article, It came out in December 2021, I will not be covering UNIX or Windows, only Linux

We will be focusing on the newer system systemd - we will not talk about its ancestor (sysV) or competitors (upstart..)

Definition

All processes running on the system are child processes of the systemd init process. It is an init system used to boostrap you from the kernel to user space.

image

image

systemd is rather new, as It was developped in 2010 and stable as of 2015. It is rapidly becoming the most used init process, but has some concerns on its inner security.

It will be considered as a system and service manager. For those that haven’t noticed, It is a play on words refering to its quick adapting ability, but for real, the d in systemd refers to daemon, and If you need to refer to it, call it System daemon, not System D.

It is hard to define systemd as a good or bad news for Linux. While It is praised by developers and users alike for its reliable parallelism during boot and centralized management of processes, daemons, services and mount points, It strayed away from the UNIX philosophy by its design (e.g. mission creep/bloat feeling).

We will focus on the service management part on systemd and the init process will be covered in another article.

What does systemd manage ?

First, It does NOT manage anything in /etc/init.d/. You should never add configuration there, as It will have no effect. There is backwards compatibility with SysV init scripts, but they will not be searched in this deprecated directory.

You can explore /etc/systemd/ instead, It gives an idea of the inner architecture

image

You can analyze each file full configuration with systemd-analyze cat-config [PATH_TO_FILE]

At its core, systemd manages units, and there is 11 available, highlighted in bold are the most important:

UnitsDescription
ServiceStart and control daemons and processes they consist of, most used type
SocketEncapsulate local IPC or network sockets in the system, useful for socket-based activation
TargetUseful to group other units through a chain of dependencies
DeviceExpose kernel devices and may be used to implement device-based activation
MountControl mount points in the file system
AutomountFor on-demand mounting of file systems (hot-plug..)
TimerUseful for triggering activation of other units based on timers
SwapSimilar to mount units, encapsulate memory swap components of the operating system
PathUsed to activate other services when file system objects change
SliceGroup and manage processes and resources (cgroups)
ScopeSimilar to service units, but for foreign processes management (e.g. init)

Units are named after their configuration files, which can include positive or negative requirement dependencies as well as ordering.

One example of such unit is the cron daemon, used for scheduling your batch.

image

To put it into perspective, my CentOS uses 370 unit files, with 141 loaded units

image

image

How are units made ?

Each units is configured through a plain-text files, with a .ini type syntax.

systemd stores them in three location, depending on their usage

PathType of unit
/usr/lib/systemd/systemsystemd default unit distributed by RPM packages
/run/systemd/systemSystemd unit files created at run time. This directory takes precedence over the default
/etc/systemd/systemSystemd unit files created by systemctl enable as well as unit files added for extending a service. This directory takes precedence over the run-time one

An example of crond.service unit configuration, part of the default configuration:

image

You can notice its scheduling dependencies on After= and WantedBy ; It is also able to restart itself on a specific timer.

Note: It’s common case to have those service units configuration created in the three locations, and there is a link on higher priority paths towards the default one. Be careful when you change it, as anything written in the default unit path (in /usr/lib/) will be overwritten at each OS update.

image

Well known units

If you are interested in systemd service architecture, try out systemctl list-dependencies

image

Among all the running units (and not only services), there is a few interesting ones that you might already know:

UnitTypeUsed for
proc-sys-fs-binfmt_miscautomountall block/character devices
run-user-xxxxmountstoring files used by running processes for that user
sys-kernel-debugmountKernel debug file system
sys-kernel-tracingmountKernel Trace file system
initscopeSystem and service manager
auditdserviceSecurity auditing service
crondserviceCommand scheduler
firewalldserviceDynamic firewall daemon
NetworkManagerserviceHandles network configuration
sshdserviceOpenSSH server daemon
systemd-journaldserviceJournal service
systemd-logindserviceuser login management
user@xxxxserviceUser manager for UID xxxx
usersliceUser and session slice
dbussocketD-Bus System Message Bus Socket
networktargetNetwork component

There is many more, and you can check a unit’s critical chain with systemd-analyze critical-chain [unit]

image

If you need to have better boot time, you can check what take the longest.

Possible state of units

Let’s preface it by saying systemd does not communicate with services that have not been started by it. All is managed through a process PID, and used to query and manage the service. If you did not start your daemon through systemd, It will be impossible to query its state through systemd commands.

There is two different types of state available on an unit:

  • Loaded : If the unit file has been found, and It is enabled
  • Active : If the unit is running or stopped

Since It is required to load an unit before running it, you need to consider both types to get a unit’s status.

Unit loading

A unit has to be loaded if you need to run it. This state depends entirely on the unit configuration, and It can be one of the following:

  • loaded
  • not-found (e.g. not found in the three possibles paths)
  • bad-setting
  • error (e.g. set a masked service as enabled for example)
  • masked

An example of bad-setting, where we missed the initial / in the path

image

After correcting the issue:

image

A note on mask : It is a stronger version of disable ; It links the unit file to /dev/null, making it impossible to start them. It prohibits all kinds of activation, including enablement or manual activation. It can be used to prevent accidentally using a service that conflicts with a running one.

Once It is loaded, It will look in its configuration for its enablement state ([Install] section of the unit file). It hooks the unit into its various suggested places (e.g. the unit is automatically started on boot or when a particular kind of hardware is plugged in).

Unit activation

Your unit can be either started or stopped, but It can actually be more refined than that. A unit possesses two levels of activation state:

  • High-level (often called active), and can take the following state:
    • active
    • inactive
    • failed
    • reloading
    • activating
    • deactivating
  • Low-level called sub, whose values depend on unit-type specific detailed state of the unit You can check what substates is available per unit type with systemctl --state=help

image

Create our own service unit

Let’s create our own service unit, which will simply repeat a ping/pong in a file. It will help us understand its state, and how to use a custom file as a service. We could imagine implementing a socket, device, or any other types of units.

Two things to note before we start:

  • System services are unable to read from the standard input stream, and when started, It connects its standard input to /dev/null to prevent any interaction.
  • System services do not inherit any context (e.g. environment variables like HOME or PATH) from the invoking user and their session. It runs in a clean execution context. You can check this out by typing env for your local environment variables and systemctl show-environment for systemd environment variables in your shell.

image

image

Now, let’s create our service unit, in /etc/systemd/system

We will call it pingpong.service:

image

We write a simple script, which repeatedly write ping/pong into a named pipe

image

Let’s start it ! We check its status beforehand

image

image

We can see It created a pipe successfully

image

The script is not perfect, as It will be blocked if someone else access this pipe, as read is blocking. The script location is also not perfect, as It depends on a non-sudo user, and represents a security risk, It would be better to review its permission and put it in /usr/local/bin

Let’s stop it, and check It deleted our named pipe

image

image

All good ! It’s also possible to create a unit template, if you want to create a skeleton of your units.

Useful commands

To reload and apply unit changes:

1
2
systemctl daemon-reload
systemctl restart [UNIT_NAME]

To have an overview of overridden/modified unit files, use systemd-delta

image

To view groupings of processes system-wise, use systemd-cgls

image

Credits

https://en.wikipedia.org/wiki/Systemd

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/system_administrators_guide/chap-managing_services_with_systemd

https://www.computernetworkingnotes.com/linux-tutorials/

https://www.freedesktop.org/software/systemd/man/systemctl.html

This post is licensed under CC BY 4.0 by the author.