Table of Contents
- Understanding Systemd Basics
- Key Systemd Concepts
- 2.1 Units
- 2.2 Targets
- 2.3 Services
- Managing Services with
systemctl- 3.1 Starting, Stopping, and Restarting Services
- 3.2 Enabling/Disabling Services (Boot Persistence)
- 3.3 Checking Service Status
- Configuring Services: Unit Files
- 4.1 Unit File Locations
- 4.2 Anatomy of a Service Unit File
- 4.3 Editing Unit Files (Overrides)
- Advanced Service Management
- 5.1 Masking vs. Disabling Services
- 5.2 Timers (Cron Alternatives)
- 5.3 Service Dependencies
- Troubleshooting Services
- 6.1 Checking Logs with
journalctl - 6.2 Validating Unit Files
- 6.3 Debugging Failed Services
- 6.1 Checking Logs with
- Conclusion
- References
1. Understanding Systemd Basics
At its core, systemd is designed to manage “units”—abstract resources that represent system components. It starts as the first process (PID 1) during boot and orchestrates the initialization of all other services and system components.
Why Systemd?
- Faster Boot: Parallelizes service startup instead of sequential execution (unlike SysVinit).
- Unified Management: Handles services, sockets, timers, and mounts through a single interface (
systemctl). - On-Demand Activation: Starts services only when needed (e.g., when a network request arrives via a socket).
- Centralized Logging: Uses
journaldto aggregate logs from services, kernel, and userspace.
2. Key Systemd Concepts
To work effectively with systemd, you need to understand three core concepts: units, targets, and services.
2.1 Units
A “unit” is the basic building block of systemd. It represents a resource to manage (e.g., a service, socket, or timer) and is defined by a unit file (a plaintext configuration file).
Common unit types include:
| Unit Type | File Extension | Purpose |
|---|---|---|
| Service | .service | Manages a daemon or application (e.g., nginx.service, sshd.service). |
| Target | .target | Groups units to define system states (e.g., multi-user.target = text login). |
| Socket | .socket | Controls network sockets; enables on-demand service activation. |
| Mount | .mount | Manages filesystem mounts (e.g., /home.mount). |
| Timer | .timer | Schedules tasks (replaces cron for systemd-aware services). |
2.2 Targets
Targets are special units that group other units to define system states (similar to SysVinit runlevels). For example:
multi-user.target: Boots the system to a multi-user command-line environment (no GUI).graphical.target: Boots to a graphical desktop (depends onmulti-user.target).poweroff.target: Shuts down the system.
To list all targets, run:
systemctl list-targets
2.3 Services
A “service” is the most common unit type (.service). It defines how to start, stop, or restart a daemon (e.g., Nginx, MySQL, or SSH). Service unit files contain instructions for systemd to manage the process, such as the executable path, user context, and restart policies.
3. Managing Services with systemctl
The systemctl command is the primary tool for interacting with systemd. It lets you start, stop, enable, disable, and check the status of services.
3.1 Starting, Stopping, and Restarting Services
Use these commands to control services in the current session (changes are not persistent across reboots):
| Command | Purpose | Example |
|---|---|---|
systemctl start <service> | Start a service. | systemctl start nginx.service |
systemctl stop <service> | Stop a service. | systemctl stop nginx.service |
systemctl restart <service> | Stop and restart a service. | systemctl restart nginx.service |
systemctl reload <service> | Reload configuration without stopping. | systemctl reload nginx.service (for Nginx config changes) |
Note: The .service suffix is optional (systemd assumes it by default). For example, systemctl start nginx works the same as systemctl start nginx.service.
3.2 Enabling/Disabling Services (Boot Persistence)
To control whether a service starts automatically at boot (persistent across reboots):
| Command | Purpose | Example |
|---|---|---|
systemctl enable <service> | Enable service to start on boot. | systemctl enable nginx |
systemctl disable <service> | Disable auto-start on boot. | systemctl disable nginx |
systemctl is-enabled <service> | Check if a service is enabled. | systemctl is-enabled nginx → enabled |
3.3 Checking Service Status
To verify if a service is running and view its status:
systemctl status nginx.service
Sample output:
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2024-03-20 10:00:00 UTC; 5min ago
Docs: man:nginx(8)
Main PID: 1234 (nginx)
Tasks: 2 (limit: 1132)
Memory: 3.5M
CGroup: /system.slice/nginx.service
├─1234 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
└─1235 nginx: worker process
Key fields:
Loaded: Whether the unit file is loaded and enabled.Active: Current state (e.g.,active (running),inactive,failed).Main PID: Process ID of the main service process.
4. Configuring Services: Unit Files
To customize how a service runs (e.g., change the user, set a restart policy, or modify the executable path), you’ll need to edit its unit file.
4.1 Unit File Locations
Systemd unit files are stored in three primary directories (in order of priority, from lowest to highest):
/usr/lib/systemd/system/: Default location for vendor-provided units (e.g., from packages likenginx). Do not edit these directly—they may be overwritten during updates./etc/systemd/system/: User-customized units. Use this for modified or new services./run/systemd/system/: Runtime-generated units (temporary, not persistent across reboots).
4.2 Anatomy of a Service Unit File
A .service file has three main sections: [Unit], [Service], and [Install]. Here’s an example for Nginx (nginx.service):
[Unit]
Description=A high performance web server and a reverse proxy server
Documentation=man:nginx(8)
After=network.target remote-fs.target nss-lookup.target # Start AFTER these targets/services
[Service]
Type=forking # Daemon forks a child process (common for traditional daemons)
PIDFile=/run/nginx.pid # Path to the PID file
ExecStart=/usr/sbin/nginx -g "daemon on; master_process on;" # Command to start the service
ExecReload=/usr/sbin/nginx -s reload # Command to reload config
ExecStop=/usr/sbin/nginx -s stop # Command to stop the service
PrivateTmp=true # Isolate /tmp for the service
[Install]
WantedBy=multi-user.target # Enable this service when multi-user.target is active (boot default)
Key [Service] Directives
Customize service behavior with these common directives:
ExecStart=<command>: The command to start the service (required).ExecStop=<command>: Command to stop the service.ExecReload=<command>: Command to reload configuration.Restart=<policy>: When to restart the service (e.g.,always,on-failure,no).Restart=on-failure: Restart if the service exits with a non-zero status (useful for critical services).
RestartSec=<seconds>: Delay before restarting (e.g.,RestartSec=5for 5 seconds).User=<user>/Group=<group>: Run the service as a specific user/group (e.g.,User=nginx).WorkingDirectory=<path>: Set the working directory for the service.Environment=<KEY>=<VALUE>: Set environment variables (e.g.,Environment="PORT=8080").
4.3 Editing Unit Files (Overrides)
To avoid overwriting vendor-provided unit files, use overrides (drop-in files) instead of editing the original.
Step 1: Create an Override File
Run systemctl edit <service> to open a temporary editor for the service’s override:
systemctl edit nginx.service
This creates a directory /etc/systemd/system/nginx.service.d/ and a file override.conf inside it.
Step 2: Add Custom Directives
For example, to make Nginx restart on failure and run as the nginx user:
[Service]
User=nginx
Group=nginx
Restart=on-failure
RestartSec=5
Step 3: Apply Changes
After saving, reload systemd to apply the override:
systemctl daemon-reload
Restart the service to activate the new configuration:
systemctl restart nginx
5. Advanced Service Management
5.1 Masking vs. Disabling Services
-
Disable: Prevents the service from starting automatically on boot, but you can still start it manually with
systemctl start <service>.systemctl disable nginx -
Mask: Completely blocks the service from starting (even manually). Systemd symlinks the unit file to
/dev/null.systemctl mask nginx
To unmask:
systemctl unmask nginx
5.2 Timers: Schedule Tasks (Cron Alternatives)
Systemd timers (.timer units) schedule services to run at specific times, replacing cron for systemd-aware tasks.
Example: Daily Backup Timer
-
Create a service unit to run the backup script (
/usr/local/bin/backup.sh):sudo nano /etc/systemd/system/backup.serviceAdd:
[Unit] Description=Daily backup service [Service] Type=oneshot # Run once and exit ExecStart=/usr/local/bin/backup.sh User=backup-user -
Create a timer unit to schedule the service:
sudo nano /etc/systemd/system/backup.timerAdd:
[Unit] Description=Run daily backup at 3 AM [Timer] OnCalendar=*-*-* 03:00:00 # Every day at 3:00 AM Persistent=true # Run missed tasks on boot (if the system was off at 3 AM) [Install] WantedBy=timers.target # Enable when timers.target is active -
Enable and start the timer:
systemctl enable --now backup.timer -
List active timers:
systemctl list-timers --all
5.3 Service Dependencies
Control the order in which services start with [Unit] directives:
Requires=<service>: The service must start; if it fails, this service also fails.Wants=<service>: The service should start, but this service continues if it fails (weaker thanRequires).After=<service>: Start this service after the specified service (e.g.,After=mysql.servicefor a web app needing MySQL).Before=<service>: Start this service before the specified service.
Example: A Node.js app requiring PostgreSQL:
[Unit]
Description=Node.js API Service
After=network.target postgresql.service
Requires=postgresql.service # Fail if PostgreSQL doesn't start
6. Troubleshooting Services
6.1 Check Logs with journalctl
Systemd’s journalctl command accesses logs from journald (the systemd logging daemon). Use it to debug service failures:
| Command | Purpose |
|---|---|
journalctl -u <service> | Show logs for a specific service. |
journalctl -u nginx -f | ”Follow” live logs for Nginx. |
journalctl -u nginx --since "10min ago" | Show logs from the last 10 minutes. |
journalctl -u nginx -p err | Show only error logs (priority err). |
journalctl -b | Show logs from the current boot. |
6.2 Validate Unit Files
Check for syntax errors in unit files:
systemd-analyze verify nginx.service
6.3 Debug Failed Services
If a service fails to start:
-
Check status:
systemctl status nginx -
View logs:
journalctl -u nginx -b # Logs from current boot -
Check dependencies:
systemctl list-dependencies nginx.service # List required services -
Test the
ExecStartcommand manually:
Run theExecStartcommand from the unit file in the terminal to see if it works (e.g.,/usr/sbin/nginx -g "daemon on; master_process on;").
7. Conclusion
Systemd is a powerful tool for managing Linux services, offering flexibility, speed, and centralized control. By mastering systemctl, unit files, and advanced features like timers and dependencies, you can ensure your services run reliably and efficiently.
Start small: practice enabling/disabling services, check statuses with systemctl status, and experiment with overrides to customize behavior. Over time, you’ll leverage systemd’s full potential to automate tasks, troubleshoot issues, and optimize your system.
8. References
- systemd Official Documentation
man systemctl(manual page forsystemctl)man systemd.service(manual page for service unit files)- Red Hat Systemd Guide
- DigitalOcean: Understanding Systemd Units and Unit Files