Skip to content
Systemd: Managing Services on Linux

Systemd: Managing Services on Linux

DodaTech Updated Jun 19, 2026 7 min read

Systemd is the init system and service manager used by virtually every modern Linux distribution — responsible for booting the system, managing services, handling logging, and orchestrating the entire lifecycle of processes from power-on to shutdown.

What You’ll Learn

  • Managing services with systemctl: start, stop, enable, disable, status
  • Creating custom service units for your applications
  • Viewing logs with journalctl
  • Using timers as a modern replacement for cron
  • Understanding targets (runlevels)
  • Troubleshooting failed services

Why Systemd Matters

Systemd is the foundation of modern Linux administration. Every service on a Linux system — from SSH and Docker to your custom application — is managed by systemd. Understanding systemd means you can deploy, monitor, and troubleshoot services confidently.

Durga Antivirus Pro runs as a systemd service with automatic restart on failure, logging to journald, and a hardened service configuration.

Learning Path

    flowchart LR
  A[Linux Basics] --> B[Process Management]
  B --> C[Systemd Services<br/>You are here]
  C --> D[Service Units]
  D --> E[Timers & Targets]
  style C fill:#f90,color:#fff
  

Systemctl Basics

# Service management
sudo systemctl start nginx        # Start a service
sudo systemctl stop nginx         # Stop a service
sudo systemctl restart nginx      # Restart a service
sudo systemctl reload nginx       # Reload config without restarting
sudo systemctl status nginx       # Show detailed status

# Enable/disable at boot
sudo systemctl enable nginx       # Start on boot
sudo systemctl disable nginx      # Don't start on boot
sudo systemctl is-enabled nginx   # Check if enabled
sudo systemctl enable --now nginx # Enable and start in one command

Expected systemctl status nginx output:

● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
     Active: active (running) since Fri 2026-06-19 10:30:00 UTC
   Main PID: 12345 (nginx)
      Tasks: 3 (limit: 1137)
     Memory: 5.2M
     CGroup: /system.slice/nginx.service
             ├─12345 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
             └─12346 nginx: worker process

Creating a Service Unit

Create a service file for your application:

# /etc/systemd/system/myapp.service
[Unit]
Description=My Application Service
After=network.target postgresql.service
Wants=postgresql.service

[Service]
Type=simple
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
Environment=NODE_ENV=production
EnvironmentFile=-/etc/myapp/env.conf
ExecStart=/usr/bin/node /opt/myapp/server.js
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

Key Directives Explained

DirectivePurpose
After=Ordering — start after these units
Wants=Weak dependency (not required)
Requires=Strong dependency (unit fails if dependency fails)
Type=simpleDefault — process forks once
Type=forkingProcess forks (daemonizes) — wait for PID file
Type=oneshotRuns once and exits (for scripts)
User=/Group=Run as a specific user (security best practice)
Restart=on-failureAuto-restart on crash
RestartSec=5Wait 5 seconds before restart
LimitNOFILE=Max open file descriptors

Enable and Start

sudo systemctl daemon-reload        # Reload unit files
sudo systemctl enable myapp         # Enable at boot
sudo systemctl start myapp          # Start now
sudo systemctl status myapp         # Verify it's running

Journalctl (Logging)

Systemd collects all service logs via journald:

# View logs for a specific service
sudo journalctl -u myapp

# Follow logs in real time (like tail -f)
sudo journalctl -u myapp -f

# Last 50 lines
sudo journalctl -u myapp -n 50

# Logs for a specific time range
sudo journalctl -u myapp --since "1 hour ago"
sudo journalctl -u myapp --since "2026-06-19" --until "2026-06-20"

# Show only errors
sudo journalctl -u myapp -p err

# Follow all services
sudo journalctl -f

# Show boot logs
sudo journalctl -b

# Show previous boot logs
sudo journalctl -b -1

# Limit output size
sudo journalctl -u myapp --no-pager -n 100

# Export logs to file
sudo journalctl -u myapp > /tmp/myapp.log

Expected journalctl output:

Jun 19 10:30:01 server myapp[12345]: Server started on port 3000
Jun 19 10:30:01 server myapp[12345]: Connecting to database...
Jun 19 10:30:02 server myapp[12345]: Database connected

Systemd Timers

Timers are the systemd equivalent of cron, with better logging and dependency support:

# /etc/systemd/system/backup.service
[Unit]
Description=Daily backup service

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
User=backup
# /etc/systemd/system/backup.timer
[Unit]
Description=Run backup daily at 2 AM

[Timer]
OnCalendar=daily
Persistent=true    # Run if system was off during scheduled time
RandomizedDelaySec=300  # Random delay to avoid thundering herd

[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
sudo systemctl list-timers

Expected list-timers output:

NEXT                        LEFT     LAST                        PASSED  UNIT            ACTIVATES
Fri 2026-06-20 02:00:00   15h      Fri 2026-06-19 02:00:01   23h     backup.timer    backup.service

Targets (Runlevels)

Targets group services into boot configurations:

TargetPurposeOld Runlevel
poweroff.targetSystem shutdown0
rescue.targetSingle-user mode1
multi-user.targetMulti-user, no GUI3
graphical.targetMulti-user with GUI5
reboot.targetReboot6
# Check current target
systemctl get-default

# Change default (boot to CLI)
sudo systemctl set-default multi-user.target

# Switch to rescue mode
sudo systemctl rescue

# List all services in a target
systemctl list-dependencies multi-user.target

Troubleshooting Failed Services

# List failed services
systemctl --failed

# Check detailed status
sudo systemctl status failed-service

# View recent logs for a failed service
sudo journalctl -u failed-service -n 50 --no-pager

# Common checks:
# 1. Permission denied → check ExecStart path and User/Group
# 2. Port in use → check if another service is on the same port
# 3. Missing executable → verify binary exists
# 4. Environment variable not set → check Environment directives

# Reset a failed service
sudo systemctl reset-failed failed-service

Common Errors

1. Service Fails with “Permission Denied”

The User= in the service unit doesn’t have execute permission on the binary or script. Check ls -l /path/to/binary and sudo -u user /path/to/binary.

2. Service Starts but Immediately Stops

The ExecStart process exits. For services that should stay running, ensure the process doesn’t fork incorrectly. Check Type= matches your process behavior.

3. Port Already in Use

Check with sudo ss -tlnp | grep PORT. Stop the conflicting service or change your app’s port.

4. Environment Variables Not Set

EnvironmentFile=-/etc/myapp/env.conf (note the - prefix) — the - means “ignore if file doesn’t exist.” Double-check the path.

5. Service Not Starting at Boot

Run sudo systemctl enable myservice to create the symlink. Verify with systemctl is-enabled myservice.

6. Journalctl Shows No Logs

Ensure StandardOutput=journal and StandardError=journal are set in the service unit.

7. Service Hangs During Stop

Set TimeoutStopSec= in the service unit (default is 90 seconds). Add ExecStop= to send a proper shutdown signal.

Practice Questions

  1. What command checks if a service is running? sudo systemctl status servicename

  2. What directive auto-restarts a service when it crashes? Restart=on-failure in the [Service] section.

  3. How do you view real-time logs for a service? sudo journalctl -u servicename -f

  4. What is the difference between enable and start? enable configures the service to start at boot. start starts it immediately.

  5. What target should services use for non-GUI servers? multi-user.target — it runs the system without a graphical interface.

Challenge: Create a systemd service for a Python/Node.js web application. Include: (1) a dedicated system user, (2) auto-restart on failure, (3) environment file for configuration, (4) logging to journald, (5) a timer for a companion cleanup script. Test the service starts, stops, restarts, and survives a crash.

FAQ

Is systemd required on Linux?
Most distributions use systemd by default. Alpine Linux uses OpenRC. Some minimal containers don’t use any init system.
How do I see all running services?
systemctl list-units --type=service --state=running
What is the difference between systemd and init.d?
init.d uses shell scripts for service management. systemd uses declarative unit files, parallel startup, dependency management, and integrated logging.
Can I use systemd on WSL?
Windows Subsystem for Linux doesn’t use systemd by default. You can enable it manually, but it’s not recommended.
How do I mask a service (prevent it from starting)?
sudo systemctl mask servicename creates a symlink to /dev/null. The service can never start until unmasked.
What is a socket unit in systemd?
A socket unit (myapp.socket) listens on a port and starts the corresponding service unit only when a connection arrives — enabling on-demand service activation.

What’s Next

TutorialWhat You’ll Learn
Cron Job SchedulingAlternative task scheduling with cron
Linux Administration BasicsFoundational server management
Bash Scripting GuideWriting scripts that run as systemd services

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro. Updated 2026-06-19.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro