Mastering Services and systemd in Red Hat Enterprise Linux
Services—or daemons—are Linux's unsung heroes. They run quietly in the background, powering web servers like Apache (httpd), secure access via SSH (sshd), or databases like MySQL (mysqld). Starting on boot or on demand, they keep applications running smoothly.
In Red Hat Enterprise Linux (RHEL), systemd revolutionized service management, replacing SysVinit. This guide covers custom services, timers, logging, dependencies, and security hardening.
From SysVinit to systemd: A Quick Evolution
RHEL 6 and earlier used SysVinit with /etc/init.d/ scripts and runlevels (e.g., 3 for multi-user text mode). Limitations included sequential starts (slow boots), poor dependencies (race conditions), and scattered logs.
RHEL 7+ adopted systemd, delivering:
- Parallel startup for boots under 5 seconds.
- Precise dependency tracking.
- Structured journalctl logging.
- Units for sockets, timers, mounts, and more.
Systemd now dominates major distros—master it for any sysadmin role.
systemd Units: The Building Blocks
Unit files are simple INI configs for resources. Common types:
| Unit Type | Purpose | Example |
|---|---|---|
| service | Daemons | httpd.service |
| socket | Network/IPC (on-demand) | ssh.socket |
| target | Unit groups (runlevel replacement) | multi-user.target |
| timer | Scheduling | backup.timer |
| mount | Filesystems | /home.mount |
| device | Hardware | sda.device |
Locations:
- Packaged: /usr/lib/systemd/system/
- Custom: /etc/systemd/system/
Anatomy of a Service Unit File
Apache's httpd.service example:
[Unit]
Description=The Apache HTTP Server
After=network.target
Wants=network-online.target
[Service]
Type=notify
ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND
ExecReload=/usr/sbin/httpd $OPTIONS -k graceful
ExecStop=/usr/sbin/httpd $OPTIONS -k stop
PIDFile=/run/httpd/httpd.pid
Restart=on-failure
PrivateTmp=true
[Install]
WantedBy=multi-user.target
- [Unit]: Metadata, dependencies (After=, Requires=, Wants=).
- [Service]: Commands (Type=simple/forking/oneshot).
- [Install]: Boot targets.
Pro Tip: Run sudo systemctl daemon-reload after edits.
Creating a Custom Service
For a Node.js app at /opt/myapp/app.js:
[Unit]
Description=My Node.js App
After=network.target
[Service]
Type=simple
User=myuser
Group=mygroup
WorkingDirectory=/opt/myapp
Environment=NODE_ENV=production
ExecStart=/usr/bin/node app.js
Restart=always
RestartSec=10
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
Commands:
# systemctl daemon-reload
# systemctl enable myapp
# systemctl start myapp
# systemctl status myapp
It auto-starts and restarts on crash. (Bonus: Adapt for PostgreSQL with ExecStart=/usr/bin/postgres -D /var/lib/pgsql/data.)
Targets: The New Runlevels
| Target | Runlevel Equivalent | Use Case |
|---|---|---|
| graphical.target | 5 | GUI desktop |
| multi-user.target | 3 | Servers (no GUI) |
| rescue.target | 1/S | Recovery |
| emergency.target | N/A | Minimal shell |
# systemctl get-default
# systemctl set-default graphical.target
Essential systemctl Commands
| Action | Command | Notes |
|---|---|---|
| Start/Stop | systemctl start/stop httpd | Immediate |
| Restart/Reload | systemctl restart/reload httpd | Graceful config reload |
| Status | systemctl status httpd | PID, logs, uptime |
| Enable/Disable | systemctl enable/disable httpd | Boot control |
| List | systemctl list-units --type=service | Active services |
| Logs | journalctl -u httpd -f | Tail logs |
Logging with journalctl
Replace /var/log/messages:
journalctl -u httpd --since "2026-02-10" # By date
journalctl -p err -u httpd # Errors
journalctl -f # Real-time
journalctl --vacuum-time=2weeks # Cleanup
Dependencies and Ordering
- After=network.target: Wait for network.
- Requires=database.service: Hard dependency.
- Wants=auditd.service: Soft (optional).
- Conflicts=old-service.service: Block rivals.
Boot analysis:
# systemd-analyze blame
# systemd-analyze plot > boot.svg
Timers: Cron's Smarter Successor
backup.timer:
[Unit]
Description=Daily Backup
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
backup.service:
[Unit]
Description=Run Backup
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
# sudo systemctl enable --now backup.timer
# systemctl list-timers
Security Hardening
[Service]
PrivateTmp=true
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/log/myapp
MemoryLimit=512M
Advanced: CapabilityBoundingSet=CAP_NET_BIND_SERVICE, RestrictAddressFamilies=AF_INET.
Troubleshooting
- Fails: systemctl status myapp + journalctl -u myapp -xe.
- Masked: systemctl unmask myapp.
- Ports: Use sockets.
- OOM: MemoryLimit=512M.
- Boot: systemd-analyze blame.
Why systemd Wins
Beyond init, it manages cgroups, user sessions, and containers. Gains: 50-70% faster boots, reliable ops, unified tools.
Bonus Tips:
- OnUnitActiveSec=1h for intervals.
- systemd-run for one-offs.
- Version-control units.
- systemd-cgtop for metrics.
Systemd transforms Linux ops. Conquer it for RHEL, CentOS, or Fedora success.
No comments:
Post a Comment