systemd service failed: как читать systemctl status и journalctl и быстро найти причину

Когда сервис переходит в состояние failed, systemd фиксирует причину и сохраняет её в журнале. Задача администратора — правильно прочитать эти данные. Ниже — последовательность действий от первого взгляда на статус до извлечения конкретной ошибки из логов.

Что означает состояние failed​


Сервис попадает в failed, когда его основной процесс завершается с ненулевым кодом, падает по сигналу, не успевает запуститься за отведённое время или нарушает условия, заданные в unit-файле. Это не отдельный тип ошибки, а обобщённое состояние, за которым всегда стоит конкретная причина, записанная в журнал.

Первый шаг: systemctl status​


Команда systemctl status <unit> выводит сводку о текущем (или последнем) запуске юнита. По умолчанию показываются 10 строк лога; для полного вывода используйте --lines и --full.

Bash:
systemctl status nginx.service --lines=50 --full

Как читать вывод​


Типичный вывод содержит несколько ключевых строк:

| Строка | Что показывает |
|--------|----------------|
| Loaded: | Путь к unit-файлу, состояние загрузки и enablement-статус |
| Active: | Текущее состояние юнита |
| Main PID: | PID основного процесса |
| Status: | Текстовое сообщение от самого процесса (если сервис его отправляет) |
| CGroup: | Дерево процессов юнита |
| Последние строки | Фрагмент журнала с последними записями |

Состояния в строке Loaded​


  • loaded — unit-файл найден и корректно загружен.
  • not-found — файл юнита не существует. Проверьте имя и путь.
  • bad-setting — в unit-файле есть директива, которую systemd не смог распарсить. Частая причина failed сразу после редактирования конфига.
  • error — общая ошибка загрузки.
  • masked — юнит принудительно отключён; запустить его невозможно, пока маска не снята.

Состояния в строке Active​


  • active (running) — сервис работает.
  • failed — процесс завершился аварийно. Рядом обычно указывается причина: exit-code, signal, timeout.
  • activating — сервис в процессе запуска. Если зависает в этом состоянии, вероятно, не укладывается в отведённый таймаут.
  • deactivating — сервис останавливается.

Цветовой индикатор​


На терминалах с поддержкой цвета рядом с именем юнита отображается символ:

  • Зелёный — активен.
  • Белый — неактивен или в режиме обслуживания.
  • Красный ×failed или error.
  • Зелёная стрелка — перезагрузка (reloading).

Второй шаг: journalctl для полного лога​


systemctl status показывает только последние строки. Полный лог юнита доступен через journalctl.

Базовая фильтрация по юниту​


Bash:
journalctl -u nginx.service

Флаг -u (или --unit=) фильтрует записи по имени юнита. Дополнительно подтягиваются сообщения от systemd о самом юните и записи о coredump, если они есть.

Ограничение по времени​


Если сервис упал недавно, нет смысла листать весь журнал:

Bash:
journalctl -u nginx.service --since "-10min"
journalctl -u nginx.service --since "2025-01-15 08:00:00"
journalctl -u nginx.service --since today

Поддерживаются абсолютные даты в формате YYYY-MM-DD HH:MM:SS (при отсутствии времени подставляется 00:00:00), ключевые слова yesterday, today, tomorrow, now, а также относительные времена с префиксом - (назад от текущего момента) или + (вперёд).

Фильтрация по приоритету​


Чтобы увидеть только ошибки и критические сообщения:

Bash:
journalctl -u nginx.service -p err

Уровни: emerg (0), alert (1), crit (2), err (3), warning (4), notice (5), info (6), debug (7). При указании одного уровня показываются все сообщения этого уровня и выше по важности. Можно задать диапазон: -p warning..err.

Конкретная загрузка системы​


Если проблема воспроизводится после перезагрузки:

Bash:
journalctl -u nginx.service -b

-b без аргумента показывает текущую загрузку. -b -1 — предыдущую. Положительное смещение отсчитывает загрузки от начала журнала, отрицательное — от конца.

Конкретный вызов (invocation) юнита​


Если сервис перезапускался несколько раз и нужно посмотреть лог именно последнего запуска:

Bash:
journalctl -u nginx.service -I

-I эквивалентен --invocation=0 и показывает записи последнего вызова. Отрицательное смещение (--invocation=-1) даёт предпоследний вызов. При использовании смещения необходимо также указать имя юнита через -u. Если одновременно задан -b, вызовы ищутся в пределах указанной загрузки.

Поиск по тексту сообщения​


Если известно ключевое слово ошибки:

Bash:
journalctl -u nginx.service --grep="permission denied"

Используются PERL-совместимые регулярные выражения. Если паттерн полностью в нижнем регистре, поиск нечувствителен к регистру; иначе — чувствителен. Поведение можно переопределить флагом --case-sensitive.

Цветовая подсветка и пейджер​


При выводе на терминал строки раскрашиваются по приоритету: ERROR и выше — красным, WARNING — жёлтым, NOTICE — выделением, INFO — обычным отображением, DEBUG — серым. По умолчанию вывод прогоняется через less; для скриптов и pipe используйте --no-pager.

Третий шаг: systemctl show для машинного анализа​


Когда нужен не человекочитаемый вывод, а конкретные свойства юнита (например, для скрипта диагностики), используйте systemctl show:

Bash:
systemctl show nginx.service --property=MainPID

По умолчанию пустые свойства скрываются; --all покажет все. Свойства отражают как конфигурацию, так и runtime-состояние. Например, MainPID показывает идентификатор основного процесса. Временные параметры нормализуются в микросекунды и получают суффикс …USec, даже если в конфигурации соответствующая опция заканчивается на …Sec.

Типичные причины failed и где их искать​


Ненулевой код выхода процесса​


В выводе systemctl status строка Active: будет содержать указание на причину — например, exit-code. Сам текст ошибки ищите в логах приложения через journalctl -u.

Таймаут запуска​


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

Ошибка в unit-файле (bad-setting)​


Если после редактирования unit-файла сервис не стартует, а Loaded: показывает bad-setting, значит systemd не смог распарсить одну из директив. Проверьте синтаксис: опечатки в именах секций, неверные значения, некорректные параметры.

Зависимости не выполнены​


Если юнит зависит от другого через Requires=, Requisite=, Wants=, ConsistsOf=, BindsTo= или Upholds=, и зависимость не запустилась, дочерний юнит тоже может перейти в failed. Проверьте дерево зависимостей:

Bash:
systemctl list-dependencies nginx.service

По умолчанию рекурсивно раскрываются только target-юниты; флаг --all раскрывает все остальные. Опции --reverse, --after, --before позволяют изменить направление обхода.

Маскировка​


Если Loaded: показывает masked, юнит принудительно отключён. Запустить его невозможно, пока маска не снята. Это не ошибка конфигурации, а намеренное действие администратора.

Проверка результата после исправления​


После внесения изменений в unit-файл на диске необходимо выполнить:

Bash:
systemctl daemon-reload

Без этой команды systemd продолжает использовать старую версию unit-файла из памяти. Затем остановите и запустите сервис заново:

Bash:
systemctl stop nginx.service
systemctl start nginx.service

Убедитесь, что Active: показывает active (running), а в последних строках лога нет новых ошибок:

Bash:
systemctl status nginx.service

Быстрый доступ к failed-юнитам​


Чтобы увидеть все юниты в состоянии failed:

Bash:
systemctl --failed

Или проверить программно:

Bash:
systemctl is-failed nginx.service

Команда возвращает код 0, если юнит в состоянии failed, и ненулевой код в противном случае. Без аргумента проверяется наличие любых failed-юнитов или циклов упорядочивания в системе, что соответствует состоянию degraded.

Ограничения и нюансы​


  • systemctl status показывает информацию только о текущем или последнем вызове юнита. Для более ранних запусков и предыдущих загрузок используйте journalctl -u с фильтрацией по -b.
  • systemctl status не подходит для определения, был ли юнит уже загружен ранее: systemd подгружает юниты по мере необходимости и может выгрузить их после операции.
  • По умолчанию systemctl status обрезает строки под ширину терминала. Флаг --full отключает обрезку.
  • Доступ к системному журналу через journalctl по умолчанию имеют root и члены групп systemd-journal, adm, wheel.
  • Если журнал хранится только в памяти (без персистентного хранилища), записи теряются после перезагрузки. Для сохранения между перезагрузками необходимо настроить Storage= в journald.conf.
  • systemctl status предназначен для человекочитаемого вывода. Для программной обработки используйте systemctl show.

Порядок действий при диагностике​


  1. systemctl status <unit> — определить тип сбоя (exit-code, signal, timeout, bad-setting).
  2. journalctl -u <unit> --since "-10min" -p err — найти конкретное сообщение об ошибке.
  3. Если ошибка в unit-файле — исправить, выполнить daemon-reload, перезапустить.
  4. Если ошибка в самом приложении — читать его логи через journalctl или в файле, указанном в документации приложения.
  5. Если таймаут — проверить, что сервис успевает инициализироваться, при необходимости скорректировать допустимое время запуска.
  6. После исправления убедиться, что Active: показывает active (running) и в логах нет новых ошибок.

Источники​


 
Назад
Верх Низ