Systemd Service Management: Modern Init System for CentOS/RHEL
Systemd is the modern init system and service manager for CentOS/RHEL. This guide covers service management, unit file creation, system targets, timers, and advanced systemd features.
Systemd Fundamentals
Basic Service Management
Essential systemctl commands:
# Check service status
systemctl status nginx
systemctl status sshd.service
# Start/stop services
systemctl start httpd
systemctl stop mariadb
# Enable/disable services
systemctl enable nginx
systemctl disable firewalld
# Restart/reload services
systemctl restart httpd
systemctl reload nginx
# Check if service is active
systemctl is-active sshd
systemctl is-enabled nginx
# List all services
systemctl list-units --type=service
systemctl list-unit-files --type=service
Service Dependencies
Manage service relationships:
# Show service dependencies
systemctl list-dependencies nginx
systemctl list-dependencies --all httpd
# Show reverse dependencies
systemctl list-dependencies --reverse sshd
# Show service requirements
systemctl show nginx -p Requires
systemctl show httpd -p Wants -p After -p Before
Unit File Configuration
Creating Custom Service Units
Create systemd service files:
# Basic service unit file
cat > /etc/systemd/system/myapp.service <<EOF
[Unit]
Description=My Application Service
Documentation=https://docs.example.com
After=network.target
Wants=network-online.target
[Service]
Type=simple
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
ExecStartPre=/usr/bin/test -f /opt/myapp/config.yml
ExecStart=/usr/bin/myapp --config /opt/myapp/config.yml
ExecReload=/bin/kill -HUP \$MAINPID
ExecStop=/bin/kill -TERM \$MAINPID
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal
SyslogIdentifier=myapp
[Install]
WantedBy=multi-user.target
EOF
# Reload systemd configuration
systemctl daemon-reload
# Enable and start service
systemctl enable --now myapp.service
Advanced Service Types
Configure different service types:
# Forking service
cat > /etc/systemd/system/legacy-app.service <<EOF
[Unit]
Description=Legacy Forking Application
After=network.target
[Service]
Type=forking
PIDFile=/var/run/legacy-app.pid
ExecStart=/usr/sbin/legacy-app --daemon
ExecStop=/usr/sbin/legacy-app --stop
PrivateTmp=true
[Install]
WantedBy=multi-user.target
EOF
# Oneshot service
cat > /etc/systemd/system/backup.service <<EOF
[Unit]
Description=System Backup
After=multi-user.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
RemainAfterExit=yes
StandardOutput=journal
[Install]
WantedBy=multi-user.target
EOF
# Notify service
cat > /etc/systemd/system/advanced-app.service <<EOF
[Unit]
Description=Advanced Application with Notification
After=network-online.target
[Service]
Type=notify
NotifyAccess=main
ExecStart=/usr/bin/advanced-app
WatchdogSec=30
Restart=on-failure
RestartPreventExitStatus=SIGTERM
[Install]
WantedBy=multi-user.target
EOF
System Targets
Managing System States
Work with systemd targets:
# List all targets
systemctl list-units --type=target
# Get default target
systemctl get-default
# Set default target
systemctl set-default multi-user.target
systemctl set-default graphical.target
# Switch to target
systemctl isolate multi-user.target
systemctl isolate rescue.target
# Create custom target
cat > /etc/systemd/system/maintenance.target <<EOF
[Unit]
Description=Maintenance Mode
Requires=basic.target
Conflicts=rescue.service rescue.target
After=basic.target rescue.service rescue.target
AllowIsolate=yes
EOF
Boot Targets
Configure boot behavior:
# Emergency mode
systemctl emergency
# Rescue mode
systemctl rescue
# Reboot to specific target
systemctl reboot --boot-loader-entry=maintenance
# Configure target dependencies
systemctl add-wants multi-user.target myapp.service
systemctl add-requires graphical.target display-manager.service
Systemd Timers
Creating Timer Units
Schedule tasks with timers:
# Create timer unit
cat > /etc/systemd/system/backup.timer <<EOF
[Unit]
Description=Daily Backup Timer
Requires=backup.service
[Timer]
OnCalendar=daily
AccuracySec=1h
Persistent=true
[Install]
WantedBy=timers.target
EOF
# Complex timer schedules
cat > /etc/systemd/system/maintenance.timer <<EOF
[Unit]
Description=System Maintenance Timer
[Timer]
OnBootSec=10min
OnUnitActiveSec=1w
OnCalendar=Mon *-*-* 02:00:00
RandomizedDelaySec=30min
[Install]
WantedBy=timers.target
EOF
# Enable timer
systemctl enable --now backup.timer
# List active timers
systemctl list-timers --all
Timer Examples
Real-world timer configurations:
# Hourly job
cat > /etc/systemd/system/hourly-task.timer <<EOF
[Unit]
Description=Hourly Task
[Timer]
OnCalendar=hourly
Persistent=true
[Install]
WantedBy=timers.target
EOF
# Custom schedule
cat > /etc/systemd/system/custom-schedule.timer <<EOF
[Unit]
Description=Custom Schedule Timer
[Timer]
# Run at 2:30 AM every Monday and Thursday
OnCalendar=Mon,Thu *-*-* 02:30:00
# Run every 6 hours
OnUnitActiveSec=6h
# Run 15 minutes after boot
OnBootSec=15min
[Install]
WantedBy=timers.target
EOF
Resource Control
CPU and Memory Limits
Control service resources:
# Set resource limits in service file
cat > /etc/systemd/system/resource-limited.service <<EOF
[Unit]
Description=Resource Limited Service
[Service]
Type=simple
ExecStart=/usr/bin/app
# CPU limits
CPUQuota=50%
CPUWeight=50
# Memory limits
MemoryLimit=512M
MemoryMax=1G
# IO limits
IOWeight=10
BlockIOWeight=10
[Install]
WantedBy=multi-user.target
EOF
# Runtime resource control
systemctl set-property nginx.service CPUQuota=25%
systemctl set-property httpd.service MemoryLimit=1G
# Show resource usage
systemd-cgtop
systemctl status nginx.service | grep -E "Memory:|CPU:"
Cgroup Management
Advanced cgroup configuration:
# Configure cgroup hierarchy
cat >> /etc/systemd/system/myapp.service <<EOF
[Service]
Slice=myapp.slice
Delegate=yes
TasksMax=100
EOF
# Create custom slice
cat > /etc/systemd/system/myapp.slice <<EOF
[Unit]
Description=My Application Slice
Before=slices.target
[Slice]
CPUQuota=200%
MemoryMax=4G
IOWeight=100
EOF
Security Features
Service Sandboxing
Implement security restrictions:
# Secure service configuration
cat > /etc/systemd/system/secure-app.service <<EOF
[Unit]
Description=Secure Application
[Service]
Type=simple
ExecStart=/usr/bin/secure-app
User=appuser
Group=appgroup
# Filesystem protection
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
ReadWritePaths=/var/lib/secure-app
TemporaryFileSystem=/var:ro
# Network isolation
PrivateNetwork=yes
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
# System call filtering
SystemCallFilter=@system-service
SystemCallErrorNumber=EPERM
# Capability restrictions
NoNewPrivileges=yes
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
# Device access
PrivateDevices=yes
DevicePolicy=closed
[Install]
WantedBy=multi-user.target
EOF
Dynamic Users
Use dynamic user allocation:
# Service with dynamic user
cat > /etc/systemd/system/dynamic-app.service <<EOF
[Unit]
Description=Application with Dynamic User
[Service]
Type=simple
ExecStart=/usr/bin/app
DynamicUser=yes
StateDirectory=app
CacheDirectory=app
LogsDirectory=app
ConfigurationDirectory=app
[Install]
WantedBy=multi-user.target
EOF
Logging and Debugging
Journal Management
Work with systemd journal:
# View service logs
journalctl -u nginx.service
journalctl -u sshd -f
# Time-based filtering
journalctl --since "2023-01-01" --until "2023-12-31"
journalctl --since "1 hour ago"
journalctl --since today
# Priority filtering
journalctl -p err
journalctl -p warning..err
# Boot logs
journalctl -b
journalctl -b -1 # Previous boot
journalctl --list-boots
# Export logs
journalctl -u nginx --output=json > nginx-logs.json
journalctl -u httpd --output=export | systemd-journal-remote -o /tmp/httpd.journal
Debug Service Issues
Troubleshoot service problems:
# Enable debug logging
systemctl edit myapp.service
# Add under [Service]:
# Environment="SYSTEMD_LOG_LEVEL=debug"
# Analyze service startup
systemd-analyze verify myapp.service
systemd-analyze security myapp.service
# Check service environment
systemctl show-environment
systemctl show myapp.service --property=Environment
# Debug boot issues
systemd-analyze
systemd-analyze blame
systemd-analyze critical-chain
systemd-analyze plot > boot.svg
Advanced Features
Socket Activation
Implement on-demand service startup:
# Create socket unit
cat > /etc/systemd/system/myapp.socket <<EOF
[Unit]
Description=My App Socket
[Socket]
ListenStream=8080
Accept=no
[Install]
WantedBy=sockets.target
EOF
# Modify service for socket activation
cat >> /etc/systemd/system/myapp.service <<EOF
[Unit]
Requires=myapp.socket
After=myapp.socket
[Service]
StandardInput=socket
StandardOutput=socket
EOF
Path Monitoring
Monitor filesystem changes:
# Create path unit
cat > /etc/systemd/system/monitor-uploads.path <<EOF
[Unit]
Description=Monitor Upload Directory
[Path]
PathChanged=/var/uploads
MakeDirectory=yes
DirectoryMode=0755
[Install]
WantedBy=multi-user.target
EOF
# Associated service
cat > /etc/systemd/system/monitor-uploads.service <<EOF
[Unit]
Description=Process Uploaded Files
[Service]
Type=oneshot
ExecStart=/usr/local/bin/process-uploads.sh
EOF
Template Units
Creating Service Templates
Build reusable service templates:
# Template service file
cat > /etc/systemd/system/webapp@.service <<EOF
[Unit]
Description=Web Application %i
After=network.target
[Service]
Type=simple
User=webapp-%i
Group=webapp-%i
WorkingDirectory=/var/www/%i
ExecStart=/usr/bin/webapp --instance %i --port %i
Restart=always
[Install]
WantedBy=multi-user.target
EOF
# Use template instances
systemctl enable webapp@8081.service
systemctl enable webapp@8082.service
systemctl start webapp@8081.service
System Maintenance
Service Migration
Migrate from SysV init scripts:
# Convert init script to systemd
cat > /etc/systemd/system/legacy.service <<EOF
[Unit]
Description=Legacy Service
After=network.target
[Service]
Type=forking
ExecStart=/etc/init.d/legacy start
ExecStop=/etc/init.d/legacy stop
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
EOF
# Disable old init script
chkconfig legacy off
systemctl enable legacy.service
Systemd Housekeeping
Maintain systemd health:
# Clean up journal
journalctl --vacuum-time=1M
journalctl --vacuum-size=500M
# Remove failed units
systemctl reset-failed
# Reload all unit files
systemctl daemon-reexec
# Check for masked units
systemctl list-unit-files --state=masked
# Find broken symlinks
find /etc/systemd/system -xtype l -print
Best Practices
Service Design Guidelines
- Use appropriate service types
- Implement proper dependencies
- Configure restart policies
- Set resource limits
- Enable security features
- Use template units for similar services
- Document unit files thoroughly
Monitoring Script
#!/bin/bash
# Systemd service monitoring
echo "=== Systemd Service Health Check ==="
# Failed services
failed=$(systemctl list-units --failed --no-legend | wc -l)
echo "Failed services: $failed"
if [ $failed -gt 0 ]; then
systemctl list-units --failed
fi
# Services in degraded state
degraded=$(systemctl is-system-running)
echo "System state: $degraded"
# High resource usage
echo -e "\nTop 5 CPU consuming services:"
systemd-cgtop -n 1 -b | head -n 6
# Recent service failures
echo -e "\nRecent service failures:"
journalctl -p err -since "1 hour ago" --no-pager | grep -E "Failed|Error" | tail -5
Conclusion
Systemd provides powerful service management capabilities for CentOS/RHEL systems. Master unit files, timers, resource control, and security features to build robust and efficient system services. Regular monitoring and proper configuration ensure reliable service operation in production environments.