>
← Back to Linux

systemd Linux Init System Explained

systemd is the modern init system and service manager for Linux that replaces SysVinit. It manages system startup, running services, and processes using unit files, targets, and the systemctl command. Since 2015, it's become the default on most major distributions including Red Hat, Ubuntu, Debian, and Fedora.

What is systemd?

systemd (system daemon) is the first process that runs when your Linux system boots (PID 1). It's responsible for initializing the system, starting essential services, mounting filesystems, and managing the entire system lifecycle. Unlike its predecessor SysVinit, which used simple shell scripts in sequential order, systemd is faster, more flexible, and manages services in parallel.

The name itself reveals its purpose—it's a daemon (background process) that manages the entire system. It's written in C and maintained by the freedesktop.org project, with significant contributions from Red Hat.

Why Replace SysVinit?

SysVinit worked fine for decades, but it had limitations. Services started sequentially, meaning slower boot times. There was no built-in dependency tracking, error recovery, or service restart capabilities. Logging was inconsistent—some services wrote to syslog, others to their own files. Managing services required learning shell scripts and understanding complex run-level hierarchies (0-6).

systemd addressed these issues by introducing:

How systemd Works

Units and Unit Files

The core concept of systemd is the "unit." A unit is any resource that systemd knows how to manage. Units are defined in files located in directories like /etc/systemd/system/, /usr/lib/systemd/system/, and /run/systemd/system/. Each unit file has a .service, .socket, .target, or other extension describing what it manages.

The most common type is the service unit (.service). Here's a simple example:

[Unit]
Description=Apache Web Server
After=network.target

[Service]
Type=notify
ExecStart=/usr/sbin/httpd -DFOREGROUND
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target

The [Unit] section describes the service. The After=network.target line tells systemd to start this service only after the network is ready. The [Service] section contains the actual commands and behavior—what to run, how to reload it, and when to restart it. The [Install] section defines when this service should be enabled, which target should activate it.

Targets

Targets are systemd's version of runlevels, but more flexible. They're essentially groupings of units that should be active at the same time. The common targets are:

Most server systems boot to multi-user.target, while desktop systems boot to graphical.target. Services declare which target activates them using the WantedBy directive.

Essential systemd Commands

You interact with systemd primarily through the systemctl command. Here are the most important ones:

Service Management

# Start a service
sudo systemctl start apache2

# Stop a service
sudo systemctl stop apache2

# Restart a service
sudo systemctl restart apache2

# Reload service configuration without stopping it
sudo systemctl reload apache2

# Check service status
sudo systemctl status apache2

# Enable service to start on boot
sudo systemctl enable apache2

# Disable service from starting on boot
sudo systemctl disable apache2

# Check if service is enabled
sudo systemctl is-enabled apache2

System Information

# List all services and their status
sudo systemctl list-units --type=service

# List only active services
sudo systemctl list-units --type=service --state=running

# Show failed services
sudo systemctl list-units --type=service --state=failed

# Check boot time
systemd-analyze

# Show detailed timing of each service during boot
systemd-analyze blame

Logs and Diagnostics

# View journald logs
sudo journalctl

# Show logs for specific service
sudo journalctl -u apache2

# Show logs from last boot
sudo journalctl -b

# Follow logs in real-time
sudo journalctl -f

# Show logs since specific time
sudo journalctl --since "2024-01-15 10:00:00"

Creating Custom systemd Services

You'll often need to create systemd services for custom applications. Here's a practical example for a Python application:

[Unit]
Description=My Python Application
After=network.target

[Service]
Type=simple
User=appuser
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/python3 /opt/myapp/app.py
Restart=on-failure
RestartSec=10s
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

Save this file as /etc/systemd/system/myapp.service, then reload systemd and start your service:

sudo systemctl daemon-reload
sudo systemctl start myapp
sudo systemctl enable myapp

The key directives here: Type=simple means the process runs in the foreground. User=appuser specifies which user runs it. Restart=on-failure automatically restarts if it crashes. StandardOutput=journal sends logs to journald instead of losing them. WantedBy=multi-user.target enables it on regular system boot.

Understanding systemd Dependencies

systemd uses several dependency directives in unit files. The main ones are:

These dependencies ensure services start in the right order and with the right conditions. For example, a web application might specify After=network.target and After=postgresql.service to ensure the network and database are ready first.

Troubleshooting systemd Issues

When services don't start correctly, use these diagnostic techniques:

# Check service status with full details
sudo systemctl status myservice -l

# View actual error messages
sudo journalctl -u myservice -n 50

# Verify unit file syntax is correct
sudo systemd-analyze verify /etc/systemd/system/myservice.service

# Check all failed units
sudo systemctl list-units --failed

# Get dependency graph
systemctl list-dependencies myservice

Common issues include wrong file permissions (service can't read its executable), missing dependencies, incorrect paths, or the unit file having syntax errors. Always verify with systemd-analyze before enabling a new service.

systemd vs SysVinit: Quick Comparison

While SysVinit is rarely used now, understanding the differences clarifies why systemd won:

Key Takeaways

systemd is the modern foundation of Linux system initialization. It replaced SysVinit because it's faster, more reliable, and easier to configure. Understanding file permissions and systemctl commands helps you manage services effectively. For production systems, knowing how to write unit files and diagnose failures with journald is essential.

Whether you're deploying applications, managing services, or administering Linux systems, you'll interact with systemd daily. Its unified approach to system management makes Linux more predictable and maintainable than ever before.

Frequently Asked Questions

Is systemd the same as init?

No. systemd is the modern init system, but "init" is the generic term for the first process (PID 1). SysVinit and OpenRC are alternative init systems. Today, systemd is the default on most distributions.

Can I use SysVinit instead of systemd?

On most modern distributions, systemd is tightly integrated. You can use alternative init systems on some distributions (like Devuan or artix Linux), but they're not mainstream. Most enterprise and desktop Linux uses systemd.

What's the difference between systemctl stop and systemctl disable?

systemctl stop stops the service immediately but doesn't prevent it from starting on next boot. systemctl disable prevents it from starting automatically at boot, but doesn't stop the currently running service. Use both to fully disable a service.

Why did my service fail to start?

Run sudo systemctl status myservice -l to see the error, then check logs with sudo journalctl -u myservice. Common causes: wrong executable path, missing dependencies, insufficient permissions, or syntax errors in the unit file. Verify the unit file with systemd-analyze verify.