Every Linux server runs dozens of services in the background. Nginx serves web pages, PHP-FPM executes PHP code, MySQL stores data, SSH allows remote access, and cron runs scheduled tasks. These services start when the server boots, run continuously, and need to be managed when things go wrong or configurations change.
systemctl
is the command that controls all of these services on modern Linux distributions. It starts, stops, restarts, and inspects services. It configures which services launch at boot. Combined with
journalctl
for reading logs, it gives you complete control over everything running on your server.
This guide covers every
systemctl
operation you need for day-to-day server administration, from basic service management to reading logs and troubleshooting services that refuse to start.
What is systemd#
systemd is the init system used by virtually every modern Linux distribution: Ubuntu 16.04+, Debian 8+, CentOS 7+, Rocky Linux 8+, and Fedora. It is the first process that starts when the server boots (PID 1), and it manages the lifecycle of every other service on the system.
Before systemd, Linux used SysVinit with shell scripts in
/etc/init.d/
. Each service had its own script with start, stop, and restart functions. systemd replaced this with a unified interface (
systemctl
) and declarative configuration files called unit files.
If you are managing a web server today, you are using systemd. The tool you interact with is
systemctl
.
Checking service status#
The first thing to do when investigating a service issue is check its status.
systemctl status
sudo systemctl status nginx
nginx.service - The nginx HTTP and reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: disabled)
Active: active (running) since Tue 2026-04-01 08:15:32 UTC; 5 days ago
Main PID: 1100 (nginx)
Tasks: 5 (limit: 4915)
Memory: 42.3M
CPU: 1min 23.456s
CGroup: /system.slice/nginx.service
├─1100 "nginx: master process /usr/sbin/nginx"
├─1101 "nginx: worker process"
├─1102 "nginx: worker process"
├─1103 "nginx: worker process"
└─1104 "nginx: worker process"
Apr 01 08:15:32 web01 systemd[1]: Starting The nginx HTTP and reverse proxy server...
Apr 01 08:15:32 web01 systemd[1]: Started The nginx HTTP and reverse proxy server.
This tells you everything you need at a glance:
- Loaded – where the unit file lives and whether the service is enabled at boot
- Active – whether it is running, stopped, or failed, and for how long
- Main PID – the primary process ID
- Tasks – how many threads/processes the service is using
- Memory – current memory consumption
- CGroup – the process tree (master process and its workers)
- Log lines – the most recent journal entries for the service
If a service has failed, the status output includes the error:
nginx.service - The nginx HTTP and reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: disabled)
Active: failed (Result: exit-code) since Sun 2026-04-06 10:22:15 UTC; 2min ago
Process: 5432 ExecStartPre=/usr/bin/nginx -t (code=exited, status=1/FAILURE)
Apr 06 10:22:15 web01 nginx[5432]: nginx: [emerg] unknown directive "serv" in /etc/nginx/nginx.conf:12
Apr 06 10:22:15 web01 nginx[5432]: nginx: configuration file /etc/nginx/nginx.conf test failed
This immediately tells you that Nginx failed because of a typo in the configuration file at line 12.
Check if a service is running
For a quick yes/no check without the full status output:
systemctl is-active nginx
Returns
active
or
inactive
. The exit code is 0 for active and non-zero for inactive, making it useful in scripts:
if systemctl is-active --quiet nginx; then
echo "Nginx is running"
else
echo "Nginx is NOT running"
fi
Check if a service is enabled at boot
systemctl is-enabled nginx
Returns
enabled
or
disabled
.
Starting, stopping, and restarting services#
Start a service
sudo systemctl start nginx
Launches the service if it is not running. If the service is already running, the command does nothing.
Stop a service
sudo systemctl stop nginx
Sends a termination signal and waits for the service to shut down gracefully. Active connections are dropped. On a web server, this means visitors immediately get connection errors.
Restart a service
sudo systemctl restart nginx
Stops and then starts the service. There is a brief interruption while the service is down. For Nginx with a typical configuration, this interruption is under a second, but any in-flight requests at the moment of the stop are dropped.
Reload a service
sudo systemctl reload nginx
Tells the service to re-read its configuration files without stopping. The service stays running and continues handling requests while applying the new configuration. This is the preferred approach after configuration changes because there is zero downtime.
Not all services support reload. The ones that matter for web hosting do:
| Service | Supports reload | What happens during reload |
|---|---|---|
| Nginx | Yes | Re-reads config, gracefully replaces worker processes |
| Apache | Yes | Re-reads config, gracefully restarts workers |
| PHP-FPM | Yes | Re-reads pool config, gracefully replaces workers |
| MySQL/MariaDB | No | Must use restart |
| SSH (sshd) | Yes | Re-reads sshd_config, applies to new connections only |
| Cron | No | Re-reads crontab automatically, no restart needed |
Reload or restart
sudo systemctl reload-or-restart nginx
Tries to reload first. If the service does not support reload, it falls back to a restart. Useful in scripts where you do not want to hard-code whether a service supports reload.
When to reload vs restart
Reload after changing a configuration file (nginx.conf, PHP-FPM pool config, sshd_config). Existing connections finish normally while new connections use the updated configuration.
Restart after installing a new version of the software, when the service is stuck or leaking memory, or when you need to clear the service’s internal state completely. Restart is also necessary for services that do not support reload, like MySQL.
For Nginx specifically, always test the configuration before reloading:
sudo nginx -t && sudo systemctl reload nginx
The
nginx -t
command validates the configuration syntax. If it finds an error, the reload does not happen, and your running configuration stays intact. Without the test, a reload with a broken config could take down Nginx entirely.
Enabling and disabling services at boot#
Enable a service
sudo systemctl enable nginx
Configures the service to start automatically when the server boots. This does not start the service right now – it only affects what happens at boot.
To enable and start in one command:
sudo systemctl enable --now nginx
Disable a service
sudo systemctl disable nginx
Prevents the service from starting at boot. A disabled service that is currently running continues running until the next reboot or until you stop it manually.
To disable and stop in one command:
sudo systemctl disable --now nginx
Why enabling matters
If a service is not enabled and the server reboots (planned maintenance, kernel update, power failure), that service will not start. This is a common cause of outages after reboots. The web server comes back, but PHP-FPM or MySQL did not start because someone installed it manually and forgot to enable it.
Check which services are enabled:
systemctl list-unit-files --type=service --state=enabled
For any critical service (Nginx, PHP-FPM, MySQL, sshd), verify it shows
enabled
. If it does not:
sudo systemctl enable nginx php-fpm mysqld sshd
Listing services#
List all running services
systemctl list-units --type=service --state=running
UNIT LOAD ACTIVE SUB DESCRIPTION
crond.service loaded active running Command Scheduler
mysqld.service loaded active running MySQL Server
nginx.service loaded active running The nginx HTTP and reverse proxy server
php-fpm.service loaded active running The PHP FastCGI Process Manager
sshd.service loaded active running OpenSSH server daemon
This is the cleanest way to see what is running. Unlike
ps aux
, which shows individual processes, this shows services as logical units.
List all services including stopped ones
systemctl list-units --type=service --all
Includes services that are loaded but not running. Useful for finding services that should be running but are not.
List failed services
systemctl list-units --type=service --state=failed
Shows only services that tried to start and failed. If this list is not empty after a reboot, something needs attention.
Search for a service
If you are not sure of the exact service name:
systemctl list-units --type=service | grep php
php-fpm.service loaded active running The PHP FastCGI Process Manager
On some distributions, PHP-FPM might be
php8.3-fpm.service
instead of
php-fpm.service
. This command finds it regardless of the exact name.
Reading service logs with journalctl#
systemd captures the output of every service it manages and stores it in the journal.
journalctl
reads it.
View logs for a specific service
journalctl -u nginx
Shows all log entries for Nginx, from oldest to newest. On a busy server, this can be thousands of lines. Use the flags below to narrow it down.
Show recent logs
journalctl -u nginx -n 50
Shows the last 50 lines. This is usually the first command to run when troubleshooting. The most recent entries show the latest error or the last successful start.
Follow logs in real time
journalctl -u nginx -f
Works like
tail -f
. New log entries appear as they are written. Press Ctrl+C to stop. Useful when you are actively debugging and want to see what happens when you reload or restart a service.
Filter by time
journalctl -u nginx --since "2026-04-06 10:00" --until "2026-04-06 11:00"
Shows logs only from that one-hour window. Useful when you know approximately when an issue occurred.
journalctl -u nginx --since "1 hour ago"
Relative times work too.
Show logs from the current boot
journalctl -u nginx -b
Only shows entries since the last boot. Useful after a server reboot to see if the service started correctly.
Show logs without a pager
journalctl -u nginx --no-pager -n 100
Outputs directly to the terminal without
less
, which is useful for piping to other commands or copying output.
Common log patterns
MySQL won’t start:
journalctl -u mysqld -n 50
Look for lines mentioning “InnoDB,” “permission denied,” or “port already in use.”
PHP-FPM workers dying:
journalctl -u php-fpm -n 100 --since "1 hour ago"
Look for “exited on signal 9” (out of memory killer) or “execution timed out” (script running too long). For more on how PHP-FPM manages workers and pools, see the dedicated guide.
Nginx failing to start after config change:
journalctl -u nginx -n 20
Look for “emerg” entries that identify the configuration error and line number.
Reloading vs restarting - practical examples#
After editing nginx.conf
sudo nginx -t && sudo systemctl reload nginx
Test first, then reload. Zero downtime. If the test fails, Nginx keeps running with the previous configuration.
After changing PHP settings in php.ini
sudo systemctl restart php-fpm
PHP-FPM needs a restart (not just reload) for changes to
php.ini
like
memory_limit
,
upload_max_filesize
, or
max_execution_time
. Pool configuration changes (like
pm.max_children
) can be applied with a reload.
After a PHP-FPM version upgrade
sudo systemctl restart php-fpm
A full restart loads the new binary.
After changing MySQL configuration in my.cnf
sudo systemctl restart mysqld
MySQL does not support reload. Some variables can be changed at runtime with
SET GLOBAL
, but most configuration changes require a restart.
After updating SSH configuration
sudo systemctl reload sshd
Reload applies the new settings to new connections. Existing SSH sessions continue with the old settings. This means you can safely reload sshd without disconnecting yourself.
You can also run
systemctl status
commands on remote servers without opening an interactive session. See how to run commands over SSH for patterns like
ssh user@server "systemctl status nginx"
.
Common services on a web server#
Here are the service names you will use most often:
| Service | Unit name | What it does |
|---|---|---|
| Nginx |
nginx.service
| Web server, reverse proxy |
| Apache |
httpd.service
or
apache2.service
| Web server (RHEL vs Debian) |
| PHP-FPM |
php-fpm.service
or
php8.3-fpm.service
| PHP process manager |
| MySQL |
mysqld.service
or
mysql.service
| Database server |
| MariaDB |
mariadb.service
| Database server (MySQL fork) |
| SSH |
sshd.service
| Remote shell access |
| Cron |
crond.service
or
cron.service
| Scheduled tasks |
| Fail2ban |
fail2ban.service
| Intrusion prevention |
| Postfix |
postfix.service
| Mail server |
| Firewalld |
firewalld.service
| Firewall management |
The unit name varies between distributions. On Rocky Linux and RHEL, the web server is
httpd
, MySQL is
mysqld
, and cron is
crond
. On Ubuntu and Debian, they are
apache2
,
mysql
, and
cron
. Nginx is
nginx
everywhere.
Troubleshooting services that won't start#
When a service fails to start, follow this sequence:
1. Check the status
sudo systemctl status nginx
The status output usually includes the error. Read the log lines at the bottom.
2. Read the full log
journalctl -u nginx -n 50
If the status output was truncated, the journal has the complete error.
3. Check for port conflicts
A service will fail if another process is already using its port. For example, if Nginx cannot bind to port 80:
ss -tlnp | grep ':80'
If something else is listening on port 80, that is your problem. See how to list running processes for identifying which process to stop.
4. Check for configuration errors
Most services have a configuration test command:
sudo nginx -t # Nginx
sudo apachectl configtest # Apache
sudo php-fpm -t # PHP-FPM
sudo named-checkconf # BIND DNS
Run the test before starting the service. Fix any errors it reports.
5. Check file permissions
Services that run as non-root users (Nginx worker processes run as
www-data
or
nginx
) need read access to their configuration files and write access to their log and PID directories. Permission problems show up as “Permission denied” in the journal. See Linux file permissions for resolving ownership and permission issues.
6. Clear the failed state
After fixing the problem, systemd may still show the service as “failed” until you reset it:
sudo systemctl reset-failed nginx
sudo systemctl start nginx
Masking services#
If you want to prevent a service from being started by anything, including other services that depend on it:
sudo systemctl mask nginx
A masked service cannot be started with
systemctl start
, cannot be enabled at boot, and cannot be started as a dependency. This is stronger than
disable
.
To undo:
sudo systemctl unmask nginx
Use masking when you have replaced a service with an alternative (for example, masking
iptables
after switching to
firewalld
) and want to make sure the old one never accidentally starts.
Managing services on Hostney#
On Hostney’s managed hosting, system services like Nginx, PHP-FPM, and MySQL are managed by the platform. You do not need to start, stop, or restart them manually.
PHP settings (upload_max_filesize, max_execution_time, and others) are managed through Hosting > PHP Manager in the control panel, and changes take effect immediately. The platform handles the service reload automatically.
For customers who need command-line access, SSH is available on all plans via the Terminal Access section in the control panel. While you cannot restart system services via SSH on Hostney, you can use WP-CLI, manage files, and run diagnostic commands. If you need to check what processes are consuming resources within your container, see how to list running processes in Linux.
Quick reference#
# Check service status
systemctl status nginx
systemctl is-active nginx
systemctl is-enabled nginx
# Start, stop, restart
sudo systemctl start nginx
sudo systemctl stop nginx
sudo systemctl restart nginx
sudo systemctl reload nginx
sudo systemctl reload-or-restart nginx
# Enable/disable at boot
sudo systemctl enable nginx
sudo systemctl enable --now nginx
sudo systemctl disable nginx
# List services
systemctl list-units --type=service --state=running
systemctl list-units --type=service --state=failed
systemctl list-units --type=service --all
# Read logs
journalctl -u nginx -n 50
journalctl -u nginx -f
journalctl -u nginx --since "1 hour ago"
journalctl -u nginx -b
# Mask/unmask
sudo systemctl mask nginx
sudo systemctl unmask nginx