systemd is the init system and service manager for most modern Linux distributions. It’s responsible for starting, stopping, and managing services (daemon processes) during the boot process and throughout the system’s runtime. Think of it as the conductor of an orchestra, ensuring all the right instruments (services) start at the right time and play their part correctly.
Let’s see systemd in action by creating a simple service that just logs a message every few seconds.
First, we need to create a script that our service will run. Let’s call it /usr/local/bin/my-logging-script.sh:
#!/bin/bash
echo "My custom service is running at $(date)" >> /var/log/my-custom-service.log
Make sure this script is executable:
sudo chmod +x /usr/local/bin/my-logging-script.sh
Now, we create a systemd service unit file. These files define how systemd should manage a service. We’ll put this in /etc/systemd/system/my-custom-service.service:
[Unit]
Description=My Custom Logging Service
After=network.target
[Service]
ExecStart=/usr/local/bin/my-logging-script.sh
Restart=always
User=root
Group=root
[Install]
WantedBy=multi-user.target
Let’s break this down:
-
[Unit]Section:Description: A human-readable name for your service.After=network.target: This tellssystemdthat our service should only start after the network is up. This is good practice if your service relies on networking.
-
[Service]Section:ExecStart=/usr/local/bin/my-logging-script.sh: This is the commandsystemdwill run to start your service.Restart=always: This is a crucial directive. It tellssystemdto automatically restart the service if it crashes or exits for any reason. This makes your service resilient.User=rootandGroup=root: Specifies the user and group the service should run as. For simplicity, we’re usingroot, but in production, you’d typically create a dedicated, unprivileged user.
-
[Install]Section:WantedBy=multi-user.target: This specifies when the service should be enabled.multi-user.targetis the standard runlevel for a system with multiple users, typically after booting into a text-based multi-user environment. When yousystemctl enable,systemdcreates a symbolic link frommulti-user.target.wants/to your service file.
After creating the service file, we need to tell systemd to reload its configuration so it knows about our new service:
sudo systemctl daemon-reload
Now, let’s start our service:
sudo systemctl start my-custom-service.service
You can check its status:
sudo systemctl status my-custom-service.service
You should see output indicating it’s "active (running)".
To see it in action, check the log file:
tail /var/log/my-custom-service.log
You’ll see lines like:
My custom service is running at Mon Oct 26 10:30:00 UTC 2023
My custom service is running at Mon Oct 26 10:30:05 UTC 2023
…and so on, every 5 seconds or so (depending on your script’s execution time and system load).
To make the service start automatically on boot, we enable it:
sudo systemctl enable my-custom-service.service
This command creates the symbolic link mentioned earlier.
To stop the service:
sudo systemctl stop my-custom-service.service
And to disable it from starting on boot:
sudo systemctl disable my-custom-service.service
The most surprising true thing about systemd is that it doesn’t just manage services; it’s a "system and service manager" that orchestrates the entire boot process, not just the services that run after boot. It uses a dependency-based model where units (services, mount points, sockets, etc.) declare what they need to run and what they provide, allowing for parallel startup and more efficient system initialization.
The ExecStart directive is powerful. It doesn’t just have to be a simple script; it can be a complex command, a Python interpreter running a script, or even a shell command with pipes and redirects. For instance, you could have ExecStart=/bin/sh -c '/usr/local/bin/my-script.sh --config /etc/my-app.conf > /var/log/my-app.log 2>&1'. This flexibility allows you to encapsulate almost any process into a systemd service.
What most people don’t realize is the power of Type in the [Service] section. While simple (the default, where the ExecStart command is the main process) is common, forking is used for older daemons that fork into the background. oneshot is for tasks that run once and then exit, like systemctl enable itself. notify and dbus are for services that signal readiness to systemd in specific ways, offering more precise control over service startup completion.
The next concept you’ll likely encounter is managing dependencies between services more intricately, using directives like Requires=, Wants=, Requisite=, and BindsTo= in conjunction with After= and Before=.