Crash Recovery

Restart=, RestartSec= and Crash Recovery

Restart= decides which exits bring the service back; systemctl stop never does. The default is no. on-failure, which the manual recommends, restarts after a non-zero exit, a crash signal, a timeout or a missed watchdog ping; on-abnormal ignores exit codes (Ubuntu 225 's Apache 129 unit uses it); always restarts after any exit. The trap is the word clean: exit code 0 and death by SIGHUP, SIGINT, SIGTERM or SIGPIPE are clean, so under on-failure a plain kill stops the service for good.

A crash, then a plain kill, against Restart=on-failureShell
systemctl show hello-api -p MainPID
sudo kill -KILL $(systemctl show -p MainPID --value hello-api)    # simulate a crash
sleep 3; systemctl show hello-api -p MainPID -p NRestarts
sudo kill -TERM $(systemctl show -p MainPID --value hello-api)    # a "polite" kill
sleep 3; systemctl is-active hello-api
sudo journalctl -u hello-api -o cat --since -10s | grep -E "result|Scheduled|Deactivated"
Output
MainPID=1950
MainPID=2042
NRestarts=1
inactive
hello-api.service: Failed with result 'signal'.
hello-api.service: Scheduled restart job, restart counter is at 1.
hello-api.service: Deactivated successfully.

SIGKILL counted as a crash, so systemd 142,543 waited RestartSec=2 and started a new process; SIGTERM was clean, so the service stayed down.

Restarts are also rate-limited, by default to 5 starts in 10 seconds. A transient unit running php -r 'exit(1);' with Restart=always and the default RestartSec= of 100 ms gave up (Start request repeated too quickly) 1.4 seconds after its first start, too soon for a booting database. For a real service, put StartLimitIntervalSec=300 and StartLimitBurst=10 in [Unit], and in [Service] add RestartSteps=5 and RestartMaxDelaySec=60 (systemd 254 and later) beside RestartSec=2: the delay then roughly doubles on each attempt up to a minute.