ExecStop= и ExecStopPost=: корректная остановка службы
Задаёт команду, которой служба останавливается. Если параметр не задан, systemd просто посылает процессам сигнал завершения — для большинства служб этого достаточно.
Что делает
Важно понимать: ExecStop= не заменяет сигналы, а выполняется до них. Сначала systemd вызывает вашу команду и ждёт, затем всё равно посылает сигнал остаточным процессам. Поэтому команда должна сама завершить работу службы, а не просто сообщить о желании.
Большинству служб этот параметр вовсе не нужен: реакция на сигнал завершения — стандартное поведение программ. Он оправдан там, где нужна особая последовательность: сохранить состояние, снять регистрацию в балансировщике, дождаться завершения задач.
Где ставится. В секции [Service]. ExecStopPost= выполняется после остановки — и в случае неудачного запуска тоже.
Значения
| Значение | Что происходит |
|---|---|
ExecStop=/usr/local/bin/myapp graceful-stop | своя команда остановки; после неё systemd всё равно проверит остаточные процессы. |
ExecStop=/bin/kill -s QUIT $MAINPID | посылка особого сигнала главному процессу. |
ExecStopPost=-/bin/rm -f /run/myapp.lock | уборка после остановки, в том числе после неудачного запуска. |
Пример
Остановка особым сигналом и уборка после.
[Service]
ExecStart=/usr/local/bin/myapp
ExecStop=/bin/kill -s QUIT $MAINPID
ExecStopPost=-/bin/rm -f /run/myapp/state.lock
TimeoutStopSec=60s
Подстановка $MAINPID работает только в командах Exec*=, и только без кавычек вокруг неё.
Типичные ошибки
Ненулевой код команды остановки помечает службу упавшей, даже если она успешно остановилась. Спасает префикс с дефисом или SuccessExitStatus=.
Команда остановки, которая не дожидается завершения службы, приводит к добиванию процессов сигналом KILL по таймауту.
Обёртки вида myapp stop часто возвращают ошибку, когда процесса уже нет: отсюда код 7/NOTRUNNING на остановке.
Связанные ошибки
- status=7/NOTRUNNING в systemdКод 7/NOTRUNNING по соглашению LSB: программа не запущена. Обычно приходит от ExecStop или ExecReload, а не от запуска.
- signal=KILL (status=9/KILL) в systemdПроцесс службы убит сигналом KILL. Кто мог его послать: OOM-killer, таймаут остановки systemd, администратор.
- Failed with result 'timeout'Состояние timeout: служба не уложилась в отведённое время при запуске, остановке или перезагрузке настроек.
Рядом стоящие параметры
Где важен на практике
Источники
- systemd.service(5)
- systemd.kill(5)
- Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)