Class 49 of 55 • Advanced Linux Administration

Linux Systemd Tutorial: systemctl, journalctl & Custom Service Units

When the Linux kernel finishes hardware initialization and mounts the root filesystem, it launches the first user-space program: PID 1 (Process ID 1). On virtually all modern Linux distributions (including Ubuntu, Debian, Red Hat, Fedora, CentOS, openSUSE, and Arch), PID 1 is systemd.

systemd is a comprehensive system and service manager that replaces the aging Unix SysVinit daemon model. It provides aggressive parallel service execution, socket activation, dependency tracking, binary journal logging, and unified system state control.

Linux Boot Flow and Systemd Target Architecture

Figure 49.1: Linux Boot Stages from UEFI/BIOS to Kernel and Systemd Target Units.


1. Service Management with systemctl

The systemctl command is the primary user interface to inspect and control systemd services and units:


# Start a service in the current session
$ sudo systemctl start nginx

# Check live runtime status, PID, memory consumption, and recent log snippets
$ systemctl status nginx

# Stop a currently running service
$ sudo systemctl stop nginx

# Restart a service (full teardown and re-spawn)
$ sudo systemctl restart nginx

# Reload service configuration files on-the-fly WITHOUT dropping active connections
$ sudo systemctl reload nginx

# Enable service to start automatically during system boot (creates symlinks in /etc/systemd/system/)
$ sudo systemctl enable nginx

# Disable automatic boot startup
$ sudo systemctl disable nginx

# Enable AND start immediately with a single command
$ sudo systemctl enable --now nginx

# Mask a dangerous or conflicting service (prevents manual or automatic startup entirely)
$ sudo systemctl mask apache2
							

2. Systemd Targets vs Legacy SysVinit Runlevels

In legacy Linux systems, runlevels 0 through 6 defined system state. In modern systemd, these have been replaced by Target Units (files ending in .target):

Legacy Runlevel Modern Systemd Target Target Purpose & Environment
Runlevel 0 poweroff.target Shuts down power and halts hardware.
Runlevel 1 / S rescue.target Single-user administrative maintenance mode.
Runlevel 3 multi-user.target Full multi-user CLI mode with networking (Standard server mode).
Runlevel 5 graphical.target Full multi-user mode with GUI Desktop (GNOME, KDE).
Runlevel 6 reboot.target Shuts down services gracefully and reboots system.
N/A emergency.target Emergency minimal root shell with filesystems mounted read-only.

# View default boot target
$ systemctl get-default
graphical.target

# Change default boot target to headless text console (server mode)
$ sudo systemctl set-default multi-user.target

# Switch to a target immediately in the running session
$ sudo systemctl isolate multi-user.target
							

3. Step-by-Step: Writing a Custom Systemd Service Unit

When deploying custom Node.js, Python, or Go microservices, you should register them as systemd units so Linux automatically restarts them on crash and launches them on boot.

Create a unit configuration file under /etc/systemd/system/myapp.service:


[Unit]
Description=My Custom Enterprise Python Microservice
Documentation=https://veewom.com/docs
After=network.target mysql.service
Wants=mysql.service

[Service]
Type=simple
User=appuser
Group=appuser
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/python3 /opt/myapp/server.py --port 8080
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
RestartSec=5s
Environment=ENVIRONMENT=production
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
							

Activating the New Service:


# 1. Instruct systemd to re-scan unit files on disk
$ sudo systemctl daemon-reload

# 2. Enable and start the new microservice
$ sudo systemctl enable --now myapp.service

# 3. Verify healthy running status
$ systemctl status myapp.service
● myapp.service - My Custom Enterprise Python Microservice
     Loaded: loaded (/etc/systemd/system/myapp.service; enabled; vendor preset: enabled)
     Active: active (running) since Sun 2026-11-02 08:30:15 UTC; 12s ago
   Main PID: 42189 (python3)
      Tasks: 4 (limit: 4915)
     Memory: 48.2M
     CGroup: /system.slice/myapp.service
             └─42189 /usr/bin/python3 /opt/myapp/server.py --port 8080
							

4. Advanced Log Inspection with journalctl

Systemd includes journald, a high-performance binary logging service. Rather than manually parsing flat text files in /var/log, use journalctl:


# View logs exclusively for a specific service
$ journalctl -u myapp.service

# Stream logs in real-time like 'tail -f'
$ journalctl -u myapp.service -f

# Filter logs from current system boot only
$ journalctl -b

# Filter logs by time window
$ journalctl --since "1 hour ago"
$ journalctl --since "2026-11-02 08:00:00" --until "2026-11-02 08:30:00"

# Filter logs strictly by error severity (emerg, alert, crit, err, warning)
$ journalctl -p err..emerg

# Check total disk space consumed by journal files and clean old entries
$ journalctl --disk-usage
$ sudo journalctl --vacuum-time=7d  # Retain only last 7 days of logs
							

Beginner Student Lab Practice Session


# Task 1: List all currently failed services on your machine
$ systemctl --failed

# Task 2: List all running timer units (modern cron alternatives)
$ systemctl list-timers

# Task 3: Check system startup boot time breakdown (blame slow services!)
$ systemd-analyze
$ systemd-analyze blame

# Task 4: View the process tree controlled by a specific service slice
$ systemd-cgls

# Task 5: Check your current machine hostname and OS metadata via systemd
$ hostnamectl
							

Frequently Asked Questions (FAQ)

restart terminates the active process entirely and spins up a brand new process with a new PID, causing a momentary interruption in active traffic. reload sends a signal (typically SIGHUP) informing the daemon to re-read its configuration files while keeping existing worker processes and active socket connections open without downtime.

Always place administrator-created or customized unit files in /etc/systemd/system/. Files located in /lib/systemd/system/ or /usr/lib/systemd/system/ are managed by distribution package managers and will be overwritten during package upgrades. Files in /etc/ take precedence.

systemctl mask <service> links the service's unit configuration file to /dev/null. This makes it impossible for any user or automated dependency to start the service, even if another enabled service lists it as a dependency. To revert, run systemctl unmask <service>.

Next Step in Your Linux Learning Path:

Secure your servers and configure encrypted remote management in Class 50: SSH Remote Administration & Security Hardening.

Continue to Class 50: SSH & Remote Access → Previous: ← Class 48: Package Managers | Full Syllabus

Share Share on Facebook Share on Twitter Share on LinkedIn Pin on Pinterest Share on Reddit

You may also like this!