systemctl is the command-line utility for controlling the systemd system and service manager.
Let’s see it in action. Imagine you’ve just deployed a new web server application, mywebapp.service.
First, you’ll want to check its status:
systemctl status mywebapp.service
This might show you:
● mywebapp.service - My Web Application
Loaded: loaded (/etc/systemd/system/mywebapp.service; enabled; vendor preset: enabled)
Active: inactive (dead) since Mon 2023-10-27 10:30:00 UTC; 1 day ago
Docs: man:mywebapp(8)
Process: 1234 ExecStart=/usr/bin/mywebapp --foreground (code=exited, status=0/SUCCESS)
Main PID: 1234 (code=exited, status=0/SUCCESS)
CPU: 0
The Active: inactive (dead) tells you it’s not running. To start it:
systemctl start mywebapp.service
And to check its status again:
systemctl status mywebapp.service
You’d hope to see:
● mywebapp.service - My Web Application
Loaded: loaded (/etc/systemd/system/mywebapp.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2023-10-28 10:30:05 UTC; 2s ago
Docs: man:mywebapp(8)
Main PID: 5678 (mywebapp)
Tasks: 1 (limit: 4915)
Memory: 5.2M
CPU: 10ms
CGroup: /system.slice/mywebapp.service
└─5678 /usr/bin/mywebapp --foreground
Notice Active: active (running). This means your application is now up and serving requests.
To ensure it starts automatically on boot:
systemctl enable mywebapp.service
This creates a symbolic link in /etc/systemd/system/multi-user.target.wants/ pointing to your service file, which systemd reads at startup.
If you need to stop the service:
systemctl stop mywebapp.service
And to restart it (useful after configuration changes):
systemctl restart mywebapp.service
Sometimes, you might want to reload the service’s configuration without fully stopping and starting it. This depends on whether the application supports it:
systemctl reload mywebapp.service
To disable automatic startup on boot:
systemctl disable mywebapp.service
This removes the symbolic link created by enable.
The core of managing services with systemctl lies in understanding the "unit files." These are typically found in /etc/systemd/system/ or /usr/lib/systemd/system/. A common unit file for a service looks like this:
[Unit]
Description=My Web Application
After=network.target
[Service]
ExecStart=/usr/bin/mywebapp --foreground
Restart=on-failure
User=myuser
Group=mygroup
[Install]
WantedBy=multi-user.target
The [Unit] section describes the service and its dependencies. After=network.target means mywebapp.service should start after the network is up. The [Service] section defines how to run the service. ExecStart is the command to execute. Restart=on-failure is a powerful directive that tells systemd to automatically restart the service if it exits with a non-zero status code, which usually indicates an error. The [Install] section defines how the service should be enabled; WantedBy=multi-user.target is standard for services that should run in a normal multi-user environment.
When you run systemctl start mywebapp.service, systemd reads the mywebapp.service unit file. It checks the After= directive to ensure dependencies are met, then executes the ExecStart command. If Restart=on-failure is set and the process exits, systemd will attempt to restart it according to its internal logic.
A common pitfall is forgetting to reload systemd’s configuration after creating or modifying a unit file. If you create /etc/systemd/system/mywebapp.service manually, systemctl won’t know about it until you tell it to rescan:
systemctl daemon-reload
This command parses all unit files and updates systemd’s internal state. Without it, commands like systemctl start mywebapp.service will fail with "Unit mywebapp.service could not be found."
You can also list all loaded units, not just services:
systemctl list-units --type=service
This gives you a comprehensive view of all active services.
To see units that have failed:
systemctl --failed
This is incredibly useful for debugging. If your service isn’t starting, it might appear here, along with other system units that encountered issues.
The systemctl command itself is a frontend to the systemd daemon. When you issue a command like systemctl start mywebapp.service, systemctl sends a message to the systemd daemon via D-Bus. The systemd daemon then performs the requested action, such as starting a process, stopping a process, or managing dependencies.
One of the most powerful aspects of systemd is its ability to manage not just services, but also other types of units like sockets, devices, mount points, and timers. For instance, you can have a mywebapp.socket unit that listens on a specific port. When a connection comes in, systemd can automatically start mywebapp.service to handle it. This is known as socket activation and is a more efficient way to manage applications that don’t need to be running all the time.
The next step in mastering service management is understanding how to create custom unit files and leverage advanced features like dependency management, resource control (cgroups), and logging integration with journalctl.