G
GuideDevOps
Lesson 11 of 17

Service Management

Part of the Linux Fundamentals tutorial series.

Systemd — The Init System

Most modern Linux distributions use Systemd as their init system. It's the first process that starts after the kernel (PID 1) and manages all services, daemons, and system processes.

Systemd uses units — configuration files that describe services, sockets, devices, or mount points. The most common unit type is the service unit.

# Systemd is PID 1
$ ps -p 1 -o comm=
systemd

systemctl — The Primary Interface

Viewing Service Status

# Check if a service is running
$ systemctl status nginx
 nginx.service - A high performance web server and reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
     Active: active (running) since Thu 2026-04-10 09:05:00 UTC; 2h 15min ago
       Docs: man:nginx(8)
    Process: 1234 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
   Main PID: 1256 (nginx)
      Tasks: 5 (limit: 4915)
     Memory: 5.2M
        CPU: 245ms
     CGroup: /system.slice/nginx.service
             └─1256 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
               ├─1257 nginx: worker process
               ├─1258 nginx: worker process
               └─1259 nginx: worker process

Status indicators:

IndicatorMeaning
(green)Service is active/running
(red)Service failed
(white)Service is inactive
(dim)Service not found
# Check if service is enabled (starts on boot)
$ systemctl is-enabled nginx
enabled
 
# Check if service is active (currently running)
$ systemctl is-active nginx
active

Starting and Stopping Services

# Start a service immediately
$ sudo systemctl start nginx
 
# Stop a running service
$ sudo systemctl stop nginx
 
# Restart a service (stop + start)
$ sudo systemctl restart nginx
 
# Reload configuration without interrupting connections
$ sudo systemctl reload nginx
 
# Reload or restart (restarts if reload isn't supported)
$ sudo systemctl reload-or-restart nginx

When to use reload vs restart:

  • reload — Keep the service running, reload config files. Use for NGINX, Apache config changes.
  • restart — Stop and start completely. Use when the binary itself changes.

Enabling and Disabling at Boot

# Enable service to start on boot
$ sudo systemctl enable nginx
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service /lib/systemd/system/nginx.service.
 
# Disable service from starting on boot
$ sudo systemctl disable nginx
Removed /etc/systemd/system/multi-user.target.wants/nginx.service.
 
# Enable AND start immediately
$ sudo systemctl enable --now nginx
 
# Disable AND stop immediately
$ sudo systemctl disable --now nginx

Listing Services

# List all active services
$ systemctl list-units --type=service
  UNIT                        LOAD   ACTIVE SUB     DESCRIPTION
  nginx.service               loaded active running A high performance web server
  ssh.service                 loaded active running OpenSSH server daemon
  docker.service              loaded active running Docker Application Container
  postgresql.service          loaded active running PostgreSQL database server
 
# List only failed services
$ systemctl list-units --type=service --state=failed
  UNIT          LOAD   ACTIVE SUB    DESCRIPTION
  backup.service loaded failed failed Backup Service
 
# List enabled services that are NOT currently active
$ systemctl list-unit-files --type=service --state=enabled

Viewing Logs for Services — journalctl

Systemd stores service logs in the journal (binary format). Use journalctl to read them.

# View all logs for a service
$ journalctl -u nginx.service
-- Journal begins at Thu 2026-04-10 08:00:00 UTC, ends at Thu 2026-04-10 11:30:00 UTC. --
Apr 10 09:05:00 server systemd[1]: Starting A high performance web server...
Apr 10 09:05:00 server nginx[1234]: 2026/04/10 09:05:00 [notice] 1234#1234: using inherited sockets...
Apr 10 09:05:00 server systemd[1]: Started A high performance web server.
 
# Follow logs in real-time (-f = follow)
$ journalctl -u nginx.service -f
 
# View last 50 lines
$ journalctl -u nginx.service -n 50
 
# View since last boot
$ journalctl -u nginx.service -b
 
# View logs from specific time range
$ journalctl -u nginx.service --since "2026-04-10 09:00:00"
$ journalctl -u nginx.service --since "1 hour ago"
$ journalctl -u nginx.service --since "today"
 
# View only error-level and worse
$ journalctl -p err -u nginx.service

Creating a Systemd Service

Service Unit File Structure

# /etc/systemd/system/myapp.service
[Unit]
Description=My Application
Documentation=https://myapp.dev/docs
After=network.target    # Start after network is up
Wants=network.target
 
[Service]
Type=simple             # simple = one process; forking = spawns children
User=myapp              # Run as this user
Group=myapp
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/bin/myapp --config /opt/myapp/config.yaml
ExecReload=/bin/kill -HUP $MAINPID    # Graceful reload signal
ExecStop=/bin/kill -TERM $MAINPID      # Graceful stop signal
Restart=on-failure      # Restart on crash
RestartSec=5            # Wait 5s before restarting
StandardOutput=journal   # Log to systemd journal
StandardError=journal
 
# Environment
EnvironmentFile=/opt/myapp/.env
 
[Install]
WantedBy=multi-user.target    # Start at boot (if enabled)

Managing Your Service

# Reload systemd to recognize new/changed unit files
$ sudo systemctl daemon-reload
 
# Start the service
$ sudo systemctl start myapp
 
# Enable at boot
$ sudo systemctl enable myapp
 
# Check status
$ systemctl status myapp
 
# View logs
$ journalctl -u myapp -f

Service Types

TypeMeaningUse Case
simpleMain process doesn't forkMost services
forkingProcess forks child, parent exitsDaemonized programs
oneshotRuns once and exitsOne-time scripts
execService is the main processContainer-like services

Troubleshooting Services

Service Won't Start

# Always check status first — it shows the error
$ sudo systemctl status nginx
 nginx.service - A high performance web server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled)
     Active: failed (Result: exit-code) since Thu 2026-04-10 09:10:00 UTC; 5s ago
    Process: 5678 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=1/FAILURE)
   Main PID: 5678 (code=exited, status=1/FAILURE)
 
Apr 10 09:10:00 server nginx[5678]: 2026/04/10 09:10:00 [emerg] 5678#5678: direct

Common issues and fixes:

# 1. Configuration error — test before starting
$ sudo nginx -t
nginx: [emerg] directive "worker_processes" is unexpected in /etc/nginx/nginx.conf:15
nginx: configuration file /etc/nginx/nginx.conf test failed
 
# 2. Port already in use
$ sudo systemctl start nginx
Job for nginx.service failed because the control process exited with error code.
See "systemctl status nginx.service" and "journalctl -xe" for details.
 
$ journalctl -u nginx | tail -20
Apr 10 09:10:00 server nginx[5678]: [emerg] 5678#5678: bind() to 0.0.0.0:80 failed (98: Address already in use)
 
# Check what's using the port
$ ss -tlnp | grep :80
 
# 3. Permission denied
$ journalctl -u nginx | grep "Permission denied"

Viewing Full Logs with Context

# -xe shows logs with additional context around the error
$ journalctl -xe -u nginx
 
# Check kernel messages (sometimes hardware-related)
$ dmesg | tail -50

Quick Reference

TaskCommand
Check statussystemctl status <service>
Start servicesudo systemctl start <service>
Stop servicesudo systemctl stop <service>
Restart servicesudo systemctl restart <service>
Reload configsudo systemctl reload <service>
Enable at bootsudo systemctl enable <service>
Disable at bootsudo systemctl disable <service>
Enable and startsudo systemctl enable --now <service>
View logsjournalctl -u <service>
Follow logsjournalctl -u <service> -f
View since bootjournalctl -b -u <service>
Check if enabledsystemctl is-enabled <service>
List active servicessystemctl list-units --type=service
List failed servicessystemctl list-units --type=service --state=failed
Reload systemd configsudo systemctl daemon-reload

Practice Challenge

  1. Run systemctl status ssh — is SSH active and enabled?
  2. Check which services are running with systemctl list-units --type=service --state=running
  3. View the last 20 lines of SSH logs with journalctl -u ssh -n 20
  4. Find any failed services with systemctl list-units --type=service --state=failed
  5. Create a simple systemd service unit for a script (or read an existing one in /etc/systemd/system/)