Сервис systemd постоянно перезапускается: читаем статус и журнал

Приложение появляется в списке процессов каждые несколько секунд и сразу исчезает. В systemctl status иногда удаётся увидеть active, но пользователи всё равно не получают ответа. Автоматический перезапуск маскирует постоянный сбой: система снова запускает программу, которая каждый раз встречает прежнее препятствие.

Разбор начинается с двух отдельных вопросов: почему процесс завершился и почему systemd решил запустить его заново. Первый относится к приложению и его окружению. Второй — к настройкам unit. Если изменить только интервал перезапуска, причина завершения останется, а наблюдать её станет немного удобнее.

Зафиксируем состояние и настройки

В примерах сервис называется api.service. Замените его именем своего unit. Следующие команды читают состояние и конфигурацию:

systemctl status api.service --no-pager --full
systemctl show api.service -p Result -p ExecMainCode -p ExecMainStatus -p NRestarts -p Restart -p RestartUSec
systemctl cat api.service

В status интересуют причина завершения, код или сигнал и время последнего перехода. В show удобно сравнивать машинные поля между наблюдениями. NRestarts помогает увидеть автоматические рестарты, но сам по себе не объясняет, почему они происходят. Последний status также не заменяет историю нескольких запусков.

systemctl cat показывает основной файл и drop-in дополнения. Это важно после ручных исправлений: значение из базового unit могло быть переопределено отдельным файлом. Сопоставляйте текст конфигурации с эффективными свойствами из show, особенно если unit недавно меняли и ещё не перечитывали manager.

Читаем журнал вокруг первого сбоя

journalctl -u api.service -b --since '-15 min' --no-pager -o short-iso
journalctl -k -b --since '-15 min' --no-pager

Первая команда выбирает сообщения unit в текущей загрузке. Вторая показывает журнал ядра за тот же период. Для полного журнала могут понадобиться дополнительные права. Пустой вывод без доступа к нужным сообщениям нельзя интерпретировать как доказательство отсутствия ошибки.

Ищите первую содержательную причину перед сообщением о запланированном перезапуске. Например, приложение могло написать, что не открыло конфигурацию, не подключилось к зависимости или не смогло занять порт. Последующее Scheduled restart job объясняет действие manager, но уже не первичную причину. Если есть признаки OOM, сопоставьте время с журналом ядра и ограничениями памяти сервиса.

Обозначение status=203/EXEC указывает на проблему выполнения команды: проверьте путь, права, интерпретатор скрипта и доступность файла в окружении unit. Код, возвращённый уже работающим приложением, разбирают по его журналу. Не переводите любой ненулевой status в вывод «сервису не хватает памяти».

Почему вручную работает, а в unit падает

Интерактивная оболочка и systemd запускают программу в разных условиях. Посмотрите User=, WorkingDirectory=, EnvironmentFile=, аргументы ExecStart= и параметры изоляции. Относительный путь к конфигурации может зависеть от рабочего каталога, а файл, доступный администратору, оказаться закрытым для пользователя сервиса.

В ExecStart shell-конструкции не появляются автоматически. Символ конвейера или перенаправления не получает привычный смысл только потому, что строка похожа на команду терминала. Если приложение запускается через отдельный скрипт, проверяйте также его shebang и режим работы процесса: systemd должен отслеживать правильный главный процесс.

Допустим, журнал сообщает о недоступном относительном пути config/app.yaml. Обоснованное исправление — согласовать рабочий каталог или передать абсолютный путь, затем проверить права пользователя unit. Простое добавление Restart=always лишь повторит ту же ошибку быстрее.

Отделим политику рестарта от причины

Restart=on-failure включает повторный запуск при определённых неуспешных исходах. Restart=always охватывает также нормальное завершение для поддерживаемых типов сервисов. Это полезно для долгоживущего приложения, однако одноразовая команда или программа, уходящая в фон при неправильном Type, может создавать неожиданный цикл. Подробности зависят от типа unit и причины выхода.

После частых запусков manager может прекратить попытки из-за StartLimitIntervalSec и StartLimitBurst. Сообщение о слишком частых стартах — следствие последовательности сбоев. Увеличение лимита или сброс failed-состояния без исправления причины вернёт прежний цикл. Сначала устраните найденное препятствие, затем выполняйте штатный запуск по принятой процедуре.

После изменения конфигурации unit manager должен перечитать её; изменение только файла конфигурации приложения может требовать другой процедуры. Проверяйте результат новым запросом приложения, журналом и наблюдением за рестартами на достаточном интервале. Однократный снимок active подтверждает лишь состояние в этот момент, а стабильная работа и успешный запрос подтверждают восстановление сервиса.

Ещё по теме

Продолжить изучение

Хотите связать Linux, контейнеры и автоматический деплой в один рабочий процесс? Посмотрите программу «DevOps-инженер с нуля: полный курс».

Продолжить на практике

  • DevOps-инженер с нуля: полный курс ↗

    Практический курс по DevOps для начинающих: от настройки Linux и сетей до сборки контейнеров, автоматизации в GitLab CI/CD, развёртывания в Kubernetes, мониторинга и восстановления данных на собственном компьютере.