Упавшая служба systemd: поиск причины и исправление
Упавшую службу systemd находят командой systemctl --failed, причину смотрят в systemctl status и journalctl -u имя -b, а после исправления сбрасывают состояние через systemctl reset-failed. Код в строке status сразу подсказывает, где ошибка: в программе, в юнит-файле или в нехватке памяти. Ниже порядок действий и таблица кодов.

Содержание
Как найти службы в состоянии failed
Обычно о проблеме узнают по красной строке [FAILED] Failed to start ... при загрузке или по тому, что сайт, VPN или принтер внезапно не работают. Первая команда при любом подозрении:
systemctl --failed
Она выводит все юниты, которые сейчас в состоянии failed: службы, точки монтирования, сокеты, таймеры. Если список пуст, системные службы в порядке. Пользовательские службы (PipeWire, Syncthing, контейнеры Podman от имени пользователя) живут в отдельном менеджере, их проверяют с ключом --user:
systemctl --user --failed
# проверить конкретную службу в скрипте
systemctl is-failed nginx.service
Команда is-failed печатает состояние и возвращает код 0, если служба упала. Это удобно для простого мониторинга через cron или таймер. Общие приёмы управления службами (запуск, остановка, автозагрузка) собраны в статье про systemctl, а здесь разберём именно разбор аварий.
Что рассказывает systemctl status
systemctl status nginx.service
Вывод выглядит громоздко, но читать нужно три места.
- Строка Active. Например,
Active: failed (Result: exit-code) since .... В скобках указан тип сбоя: exit-code, signal, timeout, core-dump или start-limit-hit. - Строка Main PID или Process. Там видно, какая команда завершилась и с каким кодом:
code=exited, status=1/FAILURE. - Последние строки журнала. Внизу status показывает около десяти последних сообщений службы. Часто причина видна прямо здесь: опечатка в конфиге, занятый порт, отсутствующий файл.
Если строки обрезаны по ширине экрана, добавьте -l и отключите пейджер: systemctl status -l --no-pager nginx. Узнать результат без лишнего текста, например для скрипта, можно через свойства юнита:
systemctl show -p Result,ExecMainStatus,NRestarts nginx.serviceЖурнал службы через journalctl
Десяти строк в status часто мало. Полный журнал службы за текущую загрузку:
journalctl -u nginx.service -b
# сразу в конец, с пояснениями systemd
journalctl -xeu nginx.service
# только ошибки всех служб за эту загрузку
journalctl -b -p err
# прошлая загрузка, если служба упала перед перезагрузкой
journalctl -u nginx.service -b -1
# за последний час
journalctl -u nginx.service --since "1 hour ago"
Ищите первое сообщение об ошибке, а не последнее. Последние строки обычно говорят только "Failed with result exit-code", а настоящая причина на несколько строк выше. Если журнал пуст или обрывается, проверьте, не ограничен ли его размер слишком жёстко: настройка хранения описана в статье про journald.
Типы сбоев и коды выхода
По коду в строке status можно сразу понять, куда копать.
| Что видно в status | Значение | Куда смотреть |
|---|---|---|
status=1/FAILURE | программа сама завершилась с ошибкой | журнал программы, её конфиг |
status=203/EXEC | не удалось запустить файл из ExecStart | путь, права на исполнение, первая строка скрипта |
status=200/CHDIR | нет каталога WorkingDirectory | путь в юните |
status=217/USER | нет пользователя из User= | создан ли пользователь |
status=226/NAMESPACE | не удалось настроить изоляцию | ReadWritePaths, ProtectSystem и несуществующие пути |
Result: signal, SIGKILL | процесс убит, часто OOM killer | journalctl -k, память |
Result: core-dump | программа упала с дампом | coredumpctl |
Result: timeout | не уложилась в TimeoutStartSec | Type= и время старта |
Result: start-limit-hit | слишком много перезапусков подряд | первую ошибку в журнале |
Коды от 200 и выше выставляет сам systemd, ещё до запуска программы. Значит, проблема в юнит-файле или окружении, а не в коде приложения.
Исправляем конфиг, юнит и зависимости
Конфиг программы
Многие демоны умеют проверять собственный конфиг без запуска. Сделайте это до рестарта, иначе служба снова упадёт:
sudo nginx -t
sudo sshd -t
sudo apachectl configtest
Ошибка в конфиге SSH особенно неприятна на удалённом сервере, поэтому после правок по статье о защите SSH всегда проверяйте его через sshd -t и держите открытой вторую сессию.
Юнит-файл
Посмотреть, какой юнит реально используется вместе со всеми дополнениями, и проверить его синтаксис:
systemctl cat myapp.service
sudo systemd-analyze verify /etc/systemd/system/myapp.service
Пакетные юниты в /usr/lib/systemd/system править напрямую нельзя: обновление пакета перезапишет изменения. Используйте дополнения, которые лягут в /etc/systemd/system/имя.service.d/:
sudo systemctl edit myapp.service
sudo systemctl daemon-reload
sudo systemctl restart myapp.service
Команда systemctl edit сама выполняет перечитывание конфигурации после сохранения, но лишний daemon-reload не повредит, если файлы правились вручную.
Зависимости
Сообщение Dependency failed for ... означает, что упала не сама служба, а то, что она требует: точка монтирования, сеть, другая служба. Цепочку покажет команда systemctl list-dependencies myapp.service. Чинить нужно первый упавший юнит в цепочке. Частый пример: несуществующий диск в /etc/fstab валит local-fs.target и вместе с ним половину загрузки.
Служба падает по кругу: Restart и лимиты
Для сетевых служб удобно, чтобы systemd поднимал их после сбоя сам. В дополнении к юниту это выглядит так:
[Unit]
StartLimitIntervalSec=300
StartLimitBurst=5
[Service]
Restart=on-failure
RestartSec=5s
Здесь служба перезапускается через 5 секунд после аварии, но не больше пяти раз за пять минут. Обратите внимание: параметры лимита относятся к секции [Unit], а не [Service]. Это частая ошибка, и тогда systemd молча использует значения по умолчанию.
Когда лимит исчерпан, служба получает статус start-limit-hit, и обычный systemctl start откажется её запускать. Сначала исправьте причину, затем сбросьте счётчик:
sudo systemctl reset-failed myapp.service
sudo systemctl start myapp.service
Без аргумента reset-failed очищает состояние failed у всех юнитов. Это удобно после серии экспериментов, чтобы systemctl --failed показывал только свежие проблемы.
Таймауты и неверный Type
Если в status написано Result: timeout, служба не успела сообщить о готовности. Причин две. Первая: программе действительно нужно много времени, например базе данных после аварийного выключения. Тогда увеличьте TimeoutStartSec= в дополнении к юниту. Вторая и более частая: тип запуска не соответствует поведению программы. Если в юните Type=forking, а программа не уходит в фон, или Type=notify, а программа не умеет отправлять уведомление, systemd ждёт сигнала, который никогда не придёт.
Медленную загрузку из-за конкретной службы видно в анализаторе:
systemd-analyze blame | head -20
systemd-analyze critical-chain
Если для вашей программы юнит пишется с нуля, начните с Type=simple или Type=exec: при них не нужны ни уход в фон, ни уведомления. Для контейнеров готовые юниты удобнее генерировать через Podman Quadlet.
Падение по сигналу: нехватка памяти и дампы
Строка Result: signal с SIGKILL почти всегда означает, что процесс убил OOM killer ядра или systemd-oomd. Проверить:
journalctl -k -b | grep -i -E "out of memory|oom"
journalctl -u systemd-oomd -b
Лечение: ограничить аппетит программы, добавить памяти или настроить swap и zram. Для служб, которые не должны съедать всю систему, есть параметр MemoryMax= в юните.
Если программа упала с ошибкой сегментации, systemd-coredump сохраняет дамп:
coredumpctl list
coredumpctl info myapp
В выводе info есть стек вызовов. Его стоит приложить к отчёту об ошибке для разработчиков, а для пакетов из репозитория сначала проверьте, нет ли уже обновления.
Перед тем как лезть в юнит, всегда выполняйте systemctl cat. Нередко выясняется, что кто-то полгода назад создал дополнение в /etc/systemd/system/имя.service.d/ и забыл о нём. Откатить все локальные изменения юнита к пакетной версии можно командой sudo systemctl revert имя.service.
Полное описание параметров Restart, Type и таймаутов есть в справке systemd.service на freedesktop.org. Если служба вам не нужна вовсе и только засоряет список, отключите её: sudo systemctl disable --now имя, а для полной блокировки запуска используйте systemctl mask.
Частые вопросы
Как посмотреть все упавшие службы?
Команда systemctl --failed покажет системные юниты в состоянии failed, а systemctl --user --failed пользовательские.
Что означает status=203/EXEC?
systemd не смог запустить файл из ExecStart: неверный путь, нет права на исполнение или ошибка в первой строке скрипта.
Как убрать состояние failed после исправления?
Выполните sudo systemctl reset-failed имя.service. Без имени команда очистит состояние у всех юнитов.
Что делать при start-limit-hit?
Найдите первую ошибку в journalctl -u имя -b, исправьте её, затем выполните reset-failed и запустите службу снова.
Как вернуть юнит к исходной версии?
Команда sudo systemctl revert имя.service удаляет локальные дополнения и копии юнита в /etc и возвращает версию из пакета.
Документация и источники
- systemd.service, freedesktop.org, 2026
- systemctl, freedesktop.org, 2026
- systemd.exec: process exit codes, freedesktop.org, 2026
- systemd, ArchWiki, 2026
Читайте также
Команды проверены на актуальных версиях дистрибутивов на момент обновления. Перед изменением системных настроек сделайте резервную копию.