Умеет, и получается честнее самописного сторожа на cron.
Механизма там два, они про разное. Первый простой: Restart=on-failure поднимает упавшую службу, а карусель бесконечных перезапусков придерживают StartLimitIntervalSec со StartLimitBurst, когда причина падения никуда не делась.
Второй как раз про зависание. Служба объявляет WatchdogSec и дальше обязана сама регулярно докладывать, что жива. Перестала докладывать, systemd её убивает и поднимает заново.
[Service]
Type=notify
ExecStart=/opt/progon/progon.py
WatchdogSec=120
Restart=on-failure
RestartSec=15
StartLimitIntervalSec=600
StartLimitBurst=4
В самом скрипте нужен доклад из рабочего цикла:
from systemd.daemon import notify
notify("READY=1")
# после каждой пачки
notify("WATCHDOG=1")
Разница с внешним сторожем вот в чём: доклад идёт изнутри цикла. Встал цикл на сетевом чтении без таймаута, доклад прекратился, служба уехала в перезапуск сама. Файл-биение делает ровно то же самое, просто руками и с задержкой на тик cron.
три монитора и ни одного свободного