Intro
When a Linux service misbehaves, the fastest fix comes from a repeatable approach. This guide shows how to use systemctl and journalctl to find failed services, read precise logs, validate unit configuration, and restart safely. It focuses on practical commands you can copy, plus a pilot plan to test changes locally before wider use.
Workflow Overview
A safe, production-minded flow:
- Identify which units are unhealthy.
- Read detailed logs for context and timing.
- Validate the unit file and overrides.
- Apply the smallest viable fix.
- Reload and restart with guardrails.
- Confirm health and watch logs.
- Document findings and next actions.
Inspect service state with systemctl
Start with a quick health scan:
- List failed services:
systemctl --failed --type=service
- See everything by state and type:
systemctl list-units --type=service --all
- Check a specific service:
systemctl status myapp.service --no-pager -l
Status shows active state, recent logs, and the main PID.
For dependencies and ordering details:
- Show dependency tree:
systemctl list-dependencies myapp.service
- Show key relations:
systemctl show -p After -p Wants -p Requires myapp.service
Read logs with journalctl
Use journalctl to get error details tied to time and boot.
Common patterns:
- Tail logs live:
journalctl -fu myapp.service --no-pager
- Show full context with explanations and jump to latest:
journalctl -xeu myapp.service --no-pager
- Restrict to current boot:
journalctl -u myapp.service -b --no-pager
- Previous boot for regressions:
journalctl -u myapp.service -b -1 --no-pager
- Time window:
journalctl -u myapp.service --since "2024-07-01 10:00" --until "2024-07-01 10:30" --no-pager
If logs look sparse, ensure persistent journaling is enabled. On many systems, creating /var/log/journal and setting Storage=persistent in /etc/systemd/journald.conf, then restarting systemd-journald, will persist logs across reboots.
Validate and fix unit configuration
Confirm what systemd is actually using:
- Show the effective unit file (including drop-ins):
systemctl cat myapp.service
- Find the on-disk fragment path:
systemctl show -p FragmentPath myapp.service
- Verify syntax:
systemd-analyze verify /etc/systemd/system/myapp.service
Check common issues:
ExecStartpath or arguments wrong.- Missing
EnvironmentFileor variables. - Permissions on the executable or working directory.
User=orGroup=not allowed to access files or ports.Restart=settings causing crash loops.
Make minimal, reviewable changes with a drop-in:
systemctl edit myapp.service
This opens an override file like /etc/systemd/system/myapp.service.d/override.conf.
Example to add an environment file and slow restarts:
[Service]
EnvironmentFile=/etc/myapp/myapp.env
Restart=on-failure
RestartSec=5s
After editing:
systemctl daemon-reload
Restart and recover safely
Prefer the least disruptive action first:
- If supported, reload config without full restart:
systemctl reload myapp.service
- Only if reload is not available or not sufficient, restart:
systemctl restart myapp.service
Helpful guardrails:
- Restart only if active (avoid starting disabled services unexpectedly):
systemctl try-restart myapp.service
- Clear failure counters before retrying after a backoff:
systemctl reset-failed myapp.service
Enable or disable explicitly:
- Check enablement:
systemctl is-enabled myapp.service
- Enable at boot (do not necessarily start now):
systemctl enable myapp.service
- Enable and start immediately:
systemctl enable --now myapp.service
- Disable cleanly:
systemctl disable myapp.service
Block accidental starts for broken units:
systemctl mask myapp.service
# later
systemctl unmask myapp.service
Validate recovery:
- Confirm active state:
systemctl is-active myapp.service
- Check listening ports if relevant:
ss -lntp | grep myapp
- Watch logs post-restart:
journalctl -fu myapp.service --no-pager
Local Pilot Plan
Start with a narrow, measurable pilot so you can inspect results locally before broader rollout.
Pilot goal: Prove you can identify, diagnose, and fix a single failing service safely.
Scope and steps:
- Choose a low-risk service (or a test service) on a non-critical host.
- Capture baseline:
systemctl status, last 200 log lines, and unit file contents. - Apply one minimal change (for example, fix an
EnvironmentFilepath via a drop-in). systemctl daemon-reload, thentry-restartorreload.- Validate:
is-activereturnsactive, logs show no new errors for 10 minutes, and the service does its primary function. - Document the exact commands and outcomes so the approach is repeatable.
Success criteria:
- Measurable error resolved.
- No collateral impact on other services.
- Rollback path confirmed (remove drop-in, daemon-reload, restart).
Optional extension:
- For timer-driven workloads, inspect timers and schedules:
systemctl list-timers --all
journalctl -u myjob.timer --no-pager
Check the paired service referenced by the timer and validate its logs and status as above.
Conclusion
A consistent flow using systemctl and journalctl shortens time to recovery: find failures fast, get precise logs, validate unit definitions, and restart with guardrails. Start with a small local pilot, prove each step, and then apply the same approach to higher-risk services. Keep changes minimal, observable, and reversible.