Linux services

Restart=on-failure Is a Policy, Not a Health Check

systemd can restart a crashed process, but only if the unit's exit semantics, rate limits, and readiness checks are understood.

Pick the policy from exit behavior

Restart=no leaves a failed service down. Restart=on-failure restarts after a non-zero exit, an unclean signal, a timeout, or a watchdog failure. It does not restart after a clean exit. Restart=always also restarts after a clean process exit.

An explicit systemctl stop is treated as an administrative action and does not cause an automatic restart. That distinction makes on-failure a sensible default for long-running network daemons that support clean shutdown.

For Type=oneshot units, restart choices are restricted. Do not paste a daemon policy into a maintenance job without checking the unit type.

Use a drop-in, not a copied unit

A drop-in changes only the policy you own and continues to receive package unit updates.

# /etc/systemd/system/example.service.d/10-restart.conf
[Service]
Restart=on-failure
RestartSec=2s
sudo systemctl daemon-reload
systemctl show example.service \
  -p Restart -p RestartUSec -p ActiveState -p NRestarts
systemd-analyze verify example.service

daemon-reload updates the manager's unit model. It does not restart the running service. The new setting applies on the next relevant process exit without creating planned downtime.

Put a ceiling on restart loops

A broken configuration can fail faster than a human can read the logs. systemd start limits stop an endless loop.

[Unit]
StartLimitIntervalSec=60s
StartLimitBurst=5

[Service]
Restart=on-failure
RestartSec=2s

Once the burst limit is reached, the unit remains failed. Fix the cause, then clear the counter with systemctl reset-failed example.service. Resetting the counter does not repair or start the service.

Verify service and application state

ActiveState=active proves that systemd sees a running unit. It does not prove that the daemon can parse its configuration or serve a request. Pair manager checks with application checks.

example-daemon validate --config /etc/example/config
systemctl is-active --quiet example.service
journalctl -u example.service -b -p warning --no-pager
curl --fail --max-time 10 https://service.example/

An actual restart-policy test needs a controlled failure and a maintenance window: record the main PID, terminate it with a signal classified as failure, wait for a new PID, and rerun the application check. Do not use a production crash as a casual demonstration.

Policy checklist

  • Confirm the unit type and clean-exit behavior.
  • Use a narrow drop-in.
  • Set a non-zero restart delay.
  • Review start-rate limits.
  • Run daemon-reload and inspect effective properties.
  • Validate configuration and a real request.
  • Review the journal after any controlled failure test.