systemd: Units, Targets, Journals & Internals
Chapter 7: systemd Deep Dive
Section titled “Chapter 7: systemd Deep Dive”Learning Objectives
Section titled “Learning Objectives”- Master systemd unit types, dependencies, and security features
- Understand the journal system and structured logging
- Know how to write production-grade systemd services
- Understand systemd timers as a cron replacement
- Troubleshoot complex systemd dependency issues
Prerequisites
Section titled “Prerequisites”What is this? (Beginner On-Ramp)
Section titled “What is this? (Beginner On-Ramp)”systemd is the master manager of a Linux system. It’s the very first program that starts (PID 1) and its job is to start all the other background services (like web servers and databases), keep them running, and manage their logs.
7.1 systemd Architecture
Section titled “7.1 systemd Architecture” systemd PID 1 — The System Manager ─────────────────────────────────────
┌────────────────────────────────────────────────────────────┐ │ systemd (PID=1) │ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌─────────────────┐ │ │ │ Unit Engine │ │ D-Bus IPC │ │ Job Queue │ │ │ │ │ │ │ │ │ │ │ │ Dependency │ │ API for │ │ Pending: │ │ │ │ resolver │ │ systemctl, │ │ - start nginx │ │ │ │ State mgr │ │ loginctl │ │ - stop redis │ │ │ └──────────────┘ └──────────────┘ └─────────────────┘ │ │ │ │ Satellite Daemons: │ │ journald udevd networkd resolved logind │ └────────────────────────────────────────────────────────────┘ │ systemctl sends commands via D-Bus journalctl reads from journald socket7.2 Unit Files: Complete Reference
Section titled “7.2 Unit Files: Complete Reference”Unit files have three sections: [Unit], [Service/Timer/Socket/...], and [Install].
[Unit] Section
Section titled “[Unit] Section”[Unit]# ─── Description ────────────────────────────────────────────Description=Short description shown in systemctl statusDocumentation=https://docs.example.com man:nginx(8)# Multiple Documentation= entries allowed
# ─── Ordering ───────────────────────────────────────────────Before=unit1.service unit2.service # This unit starts BEFORE theseAfter=network.target syslog.target # This unit starts AFTER these
# ─── Dependencies ────────────────────────────────────────────Requires=postgresql.service # Hard dep: if postgres fails, we failWants=redis.service # Soft dep: start redis if availableBindsTo=container@.service # Stronger: stop if dep stopsPartOf=group.target # Stop/restart when parent does
# ─── Conditions ──────────────────────────────────────────────ConditionPathExists=/etc/myapp/config.yaml # Only start if file existsConditionFileIsExecutable=/opt/myapp/server # Only if binary existsConditionKernelVersion=>=5.10 # Min kernel versionConditionVirtualization=no # Only on bare metalConditionHost=prod-server-01 # Only on specific host
# ─── Assertions (vs Conditions) ──────────────────────────────# Conditions: if fails, unit is skipped (not counted as failure)# Assertions: if fails, unit fails (counts as error)AssertPathExists=/var/lib/myapp # Must exist or FAIL[Service] Section — All Options
Section titled “[Service] Section — All Options”[Service]# ─── Service Type ────────────────────────────────────────────# simple: ExecStart is the main process (PID tracked)# forking: ExecStart forks; parent exits; child becomes main# notify: Like simple, but app sends sd_notify() when ready# oneshot: ExecStart exits when done; service stays "active"# dbus: Service is ready when D-Bus name acquired# idle: Like simple, but delayed until job queue emptyType=notify
# ─── Commands ─────────────────────────────────────────────────ExecStartPre=/usr/bin/test -f /etc/myapp/config.yaml # Pre-start checkExecStart=/opt/myapp/server --config /etc/myapp/config.yamlExecStartPost=/usr/bin/curl -s localhost:8080/health # Post-start checkExecReload=/bin/kill -HUP $MAINPID # Graceful reloadExecStop=/bin/kill -TERM $MAINPID # Graceful stopExecStopPost=/usr/bin/rm -f /run/myapp.pid # Cleanup
# ─── Process Identity ─────────────────────────────────────────User=myappGroup=myappWorkingDirectory=/opt/myappRootDirectory=/opt/myapp # chroot (advanced)
# ─── Environment ──────────────────────────────────────────────Environment=NODE_ENV=production PORT=8080EnvironmentFile=-/etc/myapp/env # - prefix = ignore if missingPassEnvironment=HOME LANG # Pass from systemd's environment
# ─── PID File (for Type=forking only) ─────────────────────────PIDFile=/run/myapp.pid
# ─── Restart Policy ───────────────────────────────────────────Restart=on-failure # no|always|on-success|on-failure|on-abnormal|on-abortRestartSec=10 # Wait 10s before restartStartLimitIntervalSec=300 # Rate limit window (5 minutes)StartLimitBurst=5 # Max 5 starts in that window
# ─── Timeouts ─────────────────────────────────────────────────TimeoutStartSec=30 # Fail if not ready in 30sTimeoutStopSec=30 # SIGKILL if not stopped in 30sTimeoutAbortSec=10 # After abort before SIGKILLWatchdogSec=30 # App must send keepalive every 30s
# ─── Resource Limits ──────────────────────────────────────────# Cgroup-based (v2):MemoryMax=2G # Hard limit (OOM kill)MemoryHigh=1.5G # Soft limit (throttle)CPUQuota=200% # Max 2 CPUsCPUWeight=100 # Relative CPU priorityIOWeight=100 # Relative I/O priorityTasksMax=1000 # Max PIDs/threads
# ulimit-based:LimitNOFILE=65536 # Max file descriptorsLimitNPROC=4096 # Max processesLimitCORE=infinity # Core dump size (infinity = no limit)
# ─── Security Hardening ───────────────────────────────────────NoNewPrivileges=yes # Cannot gain privileges via setuid/setgidPrivateTmp=yes # Isolated /tmpPrivateDevices=yes # No access to /dev devicesPrivateNetwork=no # (yes = no network access)PrivateUsers=no # (yes = empty user/group database)ProtectSystem=strict # /usr, /boot, /etc read-onlyProtectSystem=full # /usr, /boot read-onlyProtectHome=yes # /home, /root, /run/user inaccessibleProtectKernelModules=yes # Cannot load kernel modulesProtectKernelTunables=yes # Cannot modify kernel parametersProtectKernelLogs=yes # Cannot access kernel logProtectClock=yes # Cannot change system timeProtectControlGroups=yes # Cgroup filesystem read-onlyRestrictNamespaces=yes # Cannot create namespacesRestrictSUIDSGID=yes # Cannot create setuid/setgid filesLockPersonality=yes # Cannot change execution domain
# Allow specific paths:ReadWritePaths=/var/lib/myapp /var/log/myappReadOnlyPaths=/etc/myappInaccessiblePaths=/boot /root
# Capabilities:CapabilityBoundingSet=CAP_NET_BIND_SERVICE # Only this cap allowedAmbientCapabilities=CAP_NET_BIND_SERVICE # Grant to non-root process
# Syscall filtering:SystemCallFilter=@system-service # Common safe syscallsSystemCallFilter=~@debug @mount @reboot # Block dangerous groupsSystemCallArchitectures=native # Only native arch syscalls
# OOM priority:OOMScoreAdjust=-900 # Protect from OOM killer[Install] Section
Section titled “[Install] Section”[Install]# Defines which targets enable this unitWantedBy=multi-user.target # Normal serviceWantedBy=graphical.target # GUI service
# Alternative targetsRequiredBy=emergency.target # Must be active for emergency mode
# Alias names for this unitAlias=myapp.service myapplication.service
# Units that should be started if this one is startedAlso=myapp-monitor.service myapp-cleanup.timer7.3 systemd Timers: Replacing Cron
Section titled “7.3 systemd Timers: Replacing Cron”systemd timers are more powerful than cron: they support boot-relative timing, catch up on missed runs, integrate with the journal, and have dependencies.
[Unit]Description=Daily backup at 2 AM
[Timer]# ─── Calendar-based (like cron) ──────────────────────────────OnCalendar=*-*-* 02:00:00 # Daily at 2 AMOnCalendar=Mon..Fri 09:00:00 # Weekdays at 9 AMOnCalendar=Sat,Sun 10:00:00 # Weekends at 10 AMOnCalendar=*-*-01 00:00:00 # First of every month
# ─── Monotonic (relative to boot or last run) ─────────────────OnBootSec=5min # 5 minutes after bootOnStartupSec=10min # 10 minutes after systemd startOnUnitActiveSec=1h # 1 hour after last successful runOnUnitInactiveSec=30min # 30 minutes after last run ended
# ─── Options ─────────────────────────────────────────────────Persistent=true # Run immediately if missed while offRandomizedDelaySec=300 # Add random delay up to 5 min (avoid herd)AccuracySec=1min # Trigger within 1 minute of scheduled time
Unit=backup.service # Which service to activate
[Install]WantedBy=timers.target[Unit]Description=Backup Service
[Service]Type=oneshot # Run and exit (timer controls scheduling)User=backupExecStart=/usr/local/bin/backup.sh# Timer managementsystemctl list-timers --all # Show all timers and next run timesystemctl status backup.timer # Timer statussystemctl start backup.service # Run manually right nowjournalctl -u backup.service -n 20 # Last 20 runs' logs
# Equivalent cron expressions:# cron: "0 2 * * *" = OnCalendar=*-*-* 02:00:00# cron: "*/5 * * * *" = OnUnitActiveSec=5min7.4 The Journal: Structured Logging
Section titled “7.4 The Journal: Structured Logging”The systemd journal (journald) is the logging daemon for systemd. It collects logs from all services, the kernel, and can forward to syslog.
Journal Architecture ─────────────────────
Applications: ┌──────────┐ ┌──────────┐ ┌──────────┐ │ nginx │ │ postgres │ │ kernel │ └─────┬────┘ └─────┬────┘ └─────┬────┘ │ │ │ │ stdout/stderr │ /dev/kmsg │ │ │ ┌─────▼─────────────▼──────────────▼─────┐ │ journald │ │ Structured storage: /var/log/journal/ │ │ Each entry has: timestamp, PID, UID, │ │ service name, priority, message, etc. │ └──────────────────┬──────────────────────┘ │ ┌────────┼────────┐ ▼ ▼ ▼ journalctl rsyslog ElasticSearch (local view)(forward) (via filebeat)journalctl: Essential Usage
Section titled “journalctl: Essential Usage”# ─── Basic Usage ──────────────────────────────────────────journalctl # All journal entriesjournalctl -f # Follow (like tail -f)journalctl -n 50 # Last 50 linesjournalctl -r # Reverse order (newest first)
# ─── By Service ───────────────────────────────────────────journalctl -u nginx # All nginx logsjournalctl -u nginx -u postgresql # Multiple servicesjournalctl -u nginx -f # Follow nginx logs
# ─── By Priority ──────────────────────────────────────────journalctl -p err # Errors onlyjournalctl -p warning # Warnings and abovejournalctl -p 0..3 # emerg, alert, crit, err# Priorities: 0=emerg 1=alert 2=crit 3=err 4=warning 5=notice 6=info 7=debug
# ─── By Time ──────────────────────────────────────────────journalctl --since "2024-01-15 10:00:00"journalctl --since "1 hour ago"journalctl --since "today"journalctl --since "2024-01-15" --until "2024-01-16"journalctl -b # Current boot onlyjournalctl -b -1 # Previous bootjournalctl --list-boots # List all boots
# ─── Output Formats ───────────────────────────────────────journalctl -u nginx -o json # JSON formatjournalctl -u nginx -o json-pretty # Pretty JSONjournalctl -u nginx -o cat # Message only (no metadata)journalctl -u nginx -o verbose # All fields
# ─── Kernel Messages ──────────────────────────────────────journalctl -k # Kernel messages onlyjournalctl -k -b # Kernel messages, current bootjournalctl -k --since "1 hour ago" | grep -i error
# ─── Advanced Filtering ───────────────────────────────────journalctl _SYSTEMD_UNIT=nginx.servicejournalctl _PID=1234 # Specific PIDjournalctl _UID=1000 # Specific userjournalctl _COMM=bash # Specific executable name
# ─── Storage Management ───────────────────────────────────journalctl --disk-usage # Journal disk usagejournalctl --vacuum-size=1G # Keep only 1GB of logsjournalctl --vacuum-time=7d # Keep only last 7 daysJournal Configuration
Section titled “Journal Configuration”[Journal]Storage=persistent # persistent (disk), volatile (RAM), auto, noneCompress=yes # Compress stored dataMaxRetentionSec=30day # Delete entries older than 30 daysMaxFileSec=1week # Rotate journal files weeklySystemMaxUse=2G # Max disk space for system journalSystemKeepFree=1G # Always keep 1G freeSystemMaxFileSize=200M # Max size per journal fileRuntimeMaxUse=100M # Max RAM for volatile journalForwardToSyslog=no # Forward to syslog (if rsyslog is running)ForwardToKMsg=no # Forward to kernel message bufferForwardToConsole=no # Forward to console (for debug)MaxLevelConsole=info # Min priority to show on consoleRateLimitIntervalSec=30s # Rate limiting windowRateLimitBurst=10000 # Max messages per window7.5 Advanced systemd Features
Section titled “7.5 Advanced systemd Features”Socket Activation
Section titled “Socket Activation”Services start on-demand when a connection arrives:
[Unit]Description=My App Socket
[Socket]ListenStream=8080 # TCP portAccept=no # Pass the socket (not a new FD per connection)
[Install]WantedBy=sockets.target[Unit]Description=My AppRequires=myapp.socket # Activated by socket
[Service]ExecStart=/opt/myapp/serverStandardInput=socket # Receive the listening socket from systemd# Systemd holds the socket open even when service is stopped# First connection → systemd passes socket → service startssystemctl enable myapp.socketsystemctl start myapp.socket# Service is NOT running yetcurl localhost:8080# This triggers myapp.service to start, then serves the requestDrop-in Files (Override without Modifying Original)
Section titled “Drop-in Files (Override without Modifying Original)”# Edit vendor unit files without touching them:# Creates /etc/systemd/system/nginx.service.d/override.confsystemctl edit nginx
# Or manually:mkdir -p /etc/systemd/system/nginx.service.d/cat > /etc/systemd/system/nginx.service.d/override.conf << 'EOF'[Service]# Add environment variable without touching vendor unitEnvironment=NGINX_ENTRYPOINT_QUIET_LOGS=1# Increase memory limitMemoryMax=2G# Add pre-start hookExecStartPre=/usr/local/bin/pre-nginx-check.shEOF
systemctl daemon-reloadsystemctl restart nginx7.6 Production Runbook: systemd Service Management
Section titled “7.6 Production Runbook: systemd Service Management”# ── Service Lifecycle ─────────────────────────────────────systemctl start nginx # Start immediatelysystemctl stop nginx # Stop gracefully (SIGTERM → SIGKILL)systemctl restart nginx # Stop then startsystemctl reload nginx # Reload config without restart (SIGHUP)systemctl reload-or-restart nginx # Reload if supported, else restartsystemctl condrestart nginx # Restart only if currently running
# ── Enable/Disable ────────────────────────────────────────systemctl enable nginx # Enable on bootsystemctl disable nginx # Disable from bootsystemctl enable --now nginx # Enable AND start nowsystemctl disable --now nginx # Disable AND stop nowsystemctl is-enabled nginx # Check if enabled
# ── Status and Inspection ─────────────────────────────────systemctl status nginx # Status + last 10 log linessystemctl is-active nginx # active/inactive/failedsystemctl is-failed nginx # true/false
# ── Dependency Analysis ───────────────────────────────────systemctl list-dependencies nginx # What nginx depends onsystemctl list-dependencies --reverse nginx # What depends on nginxsystemctl list-dependencies --before nginx # Units that start beforesystemctl list-dependencies --after nginx # Units that start after
# ── Unit Files ────────────────────────────────────────────systemctl cat nginx # Show effective unit filesystemctl show nginx # All properties (machine-readable)systemctl edit nginx # Edit/create override
# ── Failed Services ───────────────────────────────────────systemctl --failed # List all failed unitssystemctl reset-failed # Clear failed state (allow retry)systemctl reset-failed nginx # Clear failed state for nginx only
# ── System Power ──────────────────────────────────────────systemctl poweroff # Power downsystemctl reboot # Rebootsystemctl suspend # Suspend (save to RAM)systemctl hibernate # Hibernate (save to disk)7.7 Troubleshooting
Section titled “7.7 Troubleshooting”Common Issues and Solutions
Section titled “Common Issues and Solutions”# Issue: Service keeps restartingsystemctl status myappjournalctl -u myapp -n 50
# Check restart countsystemctl show myapp | grep NRestarts
# If hitting StartLimitBurst:# "Start request repeated too quickly"# Fix: Reset the failure countersystemctl reset-failed myapp
# Or increase burst limit in unit:[Unit]StartLimitIntervalSec=60StartLimitBurst=10
# ─────────────────────────────────────────────────────────────# Issue: Service says "Active: active (running)" but actually dead# (Process exited but systemd doesn't know)# This means Type=simple with a daemon that backgrounds itself
# Fix: Use Type=forking with PIDFile=, or change to Type=notify# with sd_notify() in the application
# ─────────────────────────────────────────────────────────────# Issue: Dependency ordering problem# "Service A fails because Service B isn't ready yet"
# Check the orderingsystemd-analyze critical-chain myapp.service
# Add explicit ordering:[Unit]After=postgresql.service# AND ensure postgres signals readiness with Type=notify
# ─────────────────────────────────────────────────────────────# Issue: Service can't bind to port 80 (privileged port)# Root cause: service runs as non-root but port 80 < 1024
# Fix 1: Add capabilityAmbientCapabilities=CAP_NET_BIND_SERVICE
# Fix 2: Use port 8080 and redirect with iptablesiptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
# Fix 3: Enable net.ipv4.ip_unprivileged_port_start (Linux 4.11+)echo 80 > /proc/sys/net/ipv4/ip_unprivileged_port_start7.8 Interview Questions
Section titled “7.8 Interview Questions”Q1: What is the difference between Requires= and After= in a systemd unit?
Answer:
Requires=defines a dependency relationship — if the required unit fails, this unit fails too.After=defines an ordering relationship — this unit starts after the listed units. They are independent. You typically need both:Requires=postgresql.service After=postgresql.servicemeans “I need postgres, and I start after it starts.” Using onlyRequires=withoutAfter=means both units might start simultaneously (and ours might fail because postgres isn’t ready yet). Using onlyAfter=withoutRequires=means we start after postgres, but we don’t fail if postgres fails.
Q2: What is socket activation and why is it useful?
Answer: Socket activation means systemd holds open the listening socket and starts the service only when the first connection arrives. Benefits: (1) Faster boot — services don’t need to start until needed. (2) Zero-downtime restarts — while the service restarts, systemd buffers incoming connections in the kernel socket backlog. (3) Parallel startup — systemd can start dependent services immediately (they just write to the socket which is buffered) without waiting for the server to fully start. Used by D-Bus, SSH (in some distros), and many other services.
Q3: Explain the difference between Type=simple, Type=forking, and Type=notify.
Answer:
Type=simple(default): systemd considers the service started as soon asExecStartprocess begins. Doesn’t know when the service is actually ready to serve requests.Type=forking: Used when the service forks and the parent exits (traditional daemon pattern). systemd follows the child PID viaPIDFile=. Problematic because systemd waits for the fork, not for actual readiness.Type=notify: The service callssd_notify(READY=1)when it’s actually ready to serve. systemd only considers the service started after receiving this notification. Best for modern services — allows proper dependency ordering and eliminates race conditions.
7.9 Summary
Section titled “7.9 Summary”| Feature | Purpose | Key Directive |
|---|---|---|
| Service units | Run daemons/programs | ExecStart=, Type= |
| Timer units | Scheduled jobs | OnCalendar=, Persistent= |
| Socket units | On-demand activation | ListenStream= |
| Journal | Structured logging | journalctl -u service |
| Drop-ins | Override vendor units | systemctl edit |
| Hardening | Security restrictions | NoNewPrivileges=, PrivateTmp= |
Next Chapter: Chapter 8: Filesystem Internals
Section titled “Next Chapter: Chapter 8: Filesystem Internals”Prerequisites
Section titled “Prerequisites”Chapter 2 (Boot Process) — understand the boot sequence and init system.
Advantages & Disadvantages
Section titled “Advantages & Disadvantages”Advantages: Standardized across distros, parallel startup, built-in logging (journald), dependency management. Disadvantages: Monolithic and complex, steep learning curve compared to legacy SysVinit.
Common Mistakes
Section titled “Common Mistakes”- Using
systemctl stopinstead ofsystemctl disablefor permanent removal — stop only halts now; disable prevents restart on next boot. - Writing
ExecStartwith absolute paths not quoted — paths with spaces break without quoting; always verify withsystemd-analyze verify unit.service. - Forgetting
Type=notifyrequires the app to callsd_notify(READY=1)— if the app doesn’t send ready notification, systemd thinks it failed. - Setting
Restart=alwayswithoutRestartSec— rapid restart loop can fork-bomb the system. Always setRestartSec=5. - Not using
journalctl -u SERVICE --since todayfor per-service log filtering — looking at raw syslog is much slower.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Cause | Diagnosis | Fix |
|---|---|---|---|
| Service fails to start (exit code 1) | Misconfigured ExecStart or missing dependency | journalctl -u myservice -n 50; systemctl status myservice -l | Fix ExecStart path; check After= dependencies; systemd-analyze verify myservice.service |
| Service starts but immediately exits | Application exits 0 but systemd expects daemon mode | systemctl status shows 'start request repeated too quickly' | Set Type=simple (not forking) for non-daemon apps; or use Type=forking with PIDFile= |
| Timer unit not triggering | Wrong OnCalendar syntax or timer not enabled | systemctl list-timers; systemctl status mytimer.timer | Verify: systemd-analyze calendar ‘0/5:00’; enable+start the .timer unit, not the .service |
| journald consuming all disk space | No log rotation configured or rate limiting disabled | journalctl --disk-usage; du -sh /var/log/journal | Set SystemMaxUse=1G in /etc/systemd/journald.conf; systemctl restart systemd-journald |
Hands-on Lab
Section titled “Hands-on Lab”Objective: Write and manage a production-quality systemd service.
# 1. Create a simple service unitcat > /tmp/myapp.service << 'EOF'[Unit]Description=My ApplicationAfter=network.targetWants=network.target
[Service]Type=simpleUser=nobodyExecStart=/bin/sleep 300Restart=on-failureRestartSec=5StandardOutput=journalStandardError=journal
[Install]WantedBy=multi-user.targetEOF
sudo cp /tmp/myapp.service /etc/systemd/system/sudo systemctl daemon-reloadsudo systemctl start myappsudo systemctl status myapp
# 2. View its logsjournalctl -u myapp -f
# 3. Validate the unit filesystemd-analyze verify /etc/systemd/system/myapp.service
# 4. Create a timer for itcat > /tmp/myapp.timer << 'EOF'[Unit]Description=Run myapp every 5 minutes
[Timer]OnCalendar=*:0/5Persistent=true
[Install]WantedBy=timers.targetEOF
# 5. Check boot performancesystemd-analyze critical-chainExercises
Section titled “Exercises”- Write a systemd service that restarts nginx if it crashes, waits 10s before restart, and logs to the journal. Include resource limits (MemoryMax=256M).
- Create a systemd timer that runs a backup script every day at 2 AM. Verify with
systemd-analyze calendar '02:00:00'. - Use a drop-in override to increase the restart limit for an existing service:
systemctl edit nginxand setStartLimitBurst=10. - Write a service with
Type=notify— implement thesd_notify('READY=1')call in a simple Python script using thesystemdmodule. - Use
journalctlto find all services that have failed in the last 7 days:journalctl -p err --since '7 days ago'.
Revision Notes
Section titled “Revision Notes”- systemd unit types: service, timer, socket, target, mount, device, slice — each has a specific purpose.
- Service
Type=: simple (default), forking (old-style daemons), notify (sends sd_notify), oneshot (runs once). After== dependency ordering;Wants== soft dependency (failure OK);Requires== hard dependency (fails together).- Timers replace cron —
OnCalendar=uses flexible syntax;systemctl list-timersshows next trigger. - journald is structured:
journalctl -u SERVICE -S today -p err— filter by unit, time, priority. - Drop-in overrides (
systemctl edit) survive package upgrades — always prefer over editing unit files directly.
Further Reading
Section titled “Further Reading”- systemd man pages:
man 5 systemd.service,man 5 systemd.timer - systemd docs: https://systemd.io/
- Linux Service Management Made Easy with systemd — free online resource
- journald:
man 1 journalctl— complete filtering reference
Related Chapters
Section titled “Related Chapters”- Chapter 2 — systemd in the boot sequence
- Chapter 3 — Process management and cgroups
- Chapter 5 — systemd-managed cgroup slices
Last Updated: July 2026