Состояние activating означает, что systemd запустил процедуру активации юнита, но ещё не получил признак успешного завершения запуска. Исправление зависит от типа сервиса: процесс должен либо продолжить работу, либо завершить стартовый скрипт, либо отправить уведомление готовности, либо создать корректный PID-файл.
Команды ниже применимы к системным сервисам systemd. Выполняйте их с правами, достаточными для чтения журнала и управления юнитом. Вместо example.service укажите имя проблемного сервиса.
1. Зафиксировать фактическое состояние сервиса
Сначала получите краткий статус без попыток немедленно перезапускать сервис:
systemctl status example.service --no-pager -l
Затем запросите свойства, которые определяют текущую фазу запуска:
systemctl show example.service \
-p LoadState \
-p ActiveState \
-p SubState \
-p Result \
-p Type \
-p MainPID \
-p ControlPID \
-p ExecMainCode \
-p ExecMainStatus \
-p TimeoutStartUSec
Для зависшего запуска обычно характерны значения ActiveState=activating и одно из промежуточных состояний в SubState, например start, start-pre, start-post или auto-restart.
ControlPIDуказывает на процесс управляющей команды, напримерExecStartPre=или стартового скрипта.MainPIDуказывает на основной процесс, если systemd уже смог его определить.ResultиExecMainStatusпомогают отличить незавершённый запуск от циклических падений и перезапусков.
Не увеличивайте
TimeoutStartSec=до выяснения причины. Большой или бесконечный тайм-аут скрывает зависший скрипт, ошибочный тип сервиса или отсутствие уведомления готовности, но не исправляет их.
2. Найти команду, на которой остановился запуск
Просмотрите журнал текущей загрузки системы:
journalctl -u example.service --boot --no-pager
Для просмотра последних сообщений с точными временными метками используйте:
journalctl -u example.service --boot \
--since "-10 minutes" \
-o short-precise \
--no-pager
Если в журнале нет полезного сообщения, проверьте все команды юнита:
systemctl cat example.service
Особое внимание уделите директивам:
ExecStartPre=— подготовительные команды;ExecStart=— основная команда запуска;ExecStartPost=— действия после старта;Type=— условие, по которому systemd считает сервис запущенным;PIDFile=— путь к PID-файлу для некоторых сервисов типаforking;TimeoutStartSec=— максимальная длительность запуска;After=,Requires=иWants=— зависимости и порядок запуска.
Если SubState=start-pre, зависла одна из команд ExecStartPre=. Если SubState=start-post, проверяйте ExecStartPost=. Эти команды должны завершиться, прежде чем активация продолжится.
Узнать PID выполняемой управляющей команды можно так:
systemctl show example.service -p ControlPID -p MainPID
После этого исследуйте процесс стандартными средствами Linux:
ps -fp PID
Замените PID фактическим числом. Проверьте, не ожидает ли команда пользовательского ввода, недоступного файла, сокета, сетевого ресурса, блокировки или завершения дочернего процесса.
3. Проверить соответствие Type поведению программы
Type=simple
При Type=simple процесс из ExecStart= должен оставаться в foreground. Не следует запускать его через оболочку с добавлением & и не следует включать внутреннюю демонизацию, если программа умеет работать на переднем плане.
Проблемный вариант:
[Service]
Type=simple
ExecStart=/usr/local/bin/example --daemon
Если параметр --daemon заставляет программу породить фоновый процесс и завершить исходный, systemd может отслеживать не тот процесс. Предпочтительный вариант для программы с foreground-режимом:
[Service]
Type=simple
ExecStart=/usr/local/bin/example --foreground
Точное имя параметра зависит от программы. Не добавляйте --foreground, если приложение его не поддерживает; проверьте его встроенную справку или официальную документацию.
Type=notify
При Type=notify сервис остаётся в activating, пока systemd не получит уведомление READY=1 через механизм sd_notify. Если приложение не реализует этот протокол, тип выбран неверно.
Проверьте настройки:
systemctl show example.service -p Type -p NotifyAccess
Возможны два корректных решения:
- Настроить приложение так, чтобы оно отправляло
READY=1после фактической готовности. - Изменить
Type=notifyна тип, соответствующий реальному поведению программы, напримерsimpleилиexec.
Не подменяйте уведомление готовности произвольной задержкой через sleep: время запуска может измениться, а systemd всё равно не получит достоверного сигнала готовности.
Type=oneshot
Для Type=oneshot команда ExecStart= должна завершиться. Пока она работает, юнит остаётся в состоянии активации. Такой тип подходит для конечной операции: создания каталога, применения конфигурации, выполнения миграции или однократной настройки.
Типичная ошибка — запуск постоянного серверного процесса как oneshot:
[Service]
Type=oneshot
ExecStart=/usr/local/bin/example-server
Если example-server должен работать постоянно, используйте подходящий тип, обычно simple, exec или поддерживаемый приложением notify.
RemainAfterExit=yes не заставляет зависшую команду завершиться. Эта директива лишь позволяет считать юнит активным после успешного завершения команды.
Type=forking
При Type=forking стартовый процесс должен породить фоновый процесс и завершиться. Если стартовая команда не выходит или PID-файл не появляется по ожидаемому пути, сервис может долго оставаться в activating.
Проверьте конфигурацию:
systemctl show example.service -p Type -p PIDFile -p MainPID
Затем убедитесь, что путь из PIDFile= совпадает с настройкой самой программы. PID-файл должен содержать PID реально работающего основного процесса. Не создавайте PID-файл вручную и не записывайте в него PID оболочки или стартового скрипта.
Если приложение поддерживает foreground-режим, обычно надёжнее отказаться от внутренней демонизации и использовать Type=simple, exec или notify.
4. Проверить зависимости и незавершённые задания
Сервис может ожидать другой юнит. Просмотрите активные задания systemd:
systemctl list-jobs
Покажите зависимости проблемного сервиса:
systemctl list-dependencies example.service
Для анализа порядка запуска используйте:
systemd-analyze critical-chain example.service
Эта команда помогает увидеть цепочку юнитов, повлиявших на момент запуска. Она не доказывает, что последний показанный юнит завис: вывод нужно сопоставлять с журналом и текущими заданиями.
Проверьте зависимые mount-, socket-, network- и device-юниты отдельно:
systemctl status dependency.unit --no-pager -l
journalctl -u dependency.unit --boot --no-pager
Замените dependency.unit именем конкретной зависимости. Не добавляйте After=network-online.target автоматически: это оправдано только тогда, когда сервис действительно требует настроенной сети до запуска, а в системе корректно реализовано ожидание network-online.
5. Проверить синтаксис и итоговую конфигурацию юнита
Файл из /usr/lib/systemd/system или /lib/systemd/system может быть переопределён drop-in-файлом из /etc/systemd/system. Поэтому проверяйте не только исходный файл пакета, а объединённую конфигурацию:
systemctl cat example.service
Для статической проверки используйте:
systemd-analyze verify /etc/systemd/system/example.service
Если юнит поставляется пакетом и изменяется через drop-in, создайте или отредактируйте переопределение штатной командой:
systemctl edit example.service
Например, исправление типа и тайм-аута может выглядеть так:
[Service]
Type=simple
TimeoutStartSec=30s
Это только пример структуры. Значение Type должно соответствовать программе, а тайм-аут — допустимой продолжительности её запуска.
После изменения файлов перечитайте конфигурацию менеджера:
systemctl daemon-reload
6. Остановить зависший запуск и проверить исправление
Сначала попробуйте штатную остановку:
systemctl stop example.service
После исправления конфигурации сбросьте сохранённое состояние ошибки и запустите сервис:
systemctl reset-failed example.service
systemctl start example.service
Проверяйте результат сразу тремя способами:
systemctl is-active example.service
systemctl status example.service --no-pager -l
journalctl -u example.service --boot -n 50 --no-pager
Для постоянно работающего сервиса ожидается состояние active. Для успешно завершившегося oneshot итог зависит от RemainAfterExit=: без него юнит может перейти в inactive, что само по себе не означает ошибку.
Практическая последовательность диагностики
- Получить
ActiveState,SubState,Type,MainPIDиControlPID. - Просмотреть журнал юнита за текущую загрузку.
- Определить, зависла ли команда
ExecStartPre,ExecStartилиExecStartPost. - Сопоставить
Type=с реальным поведением приложения. - Для
notifyпроверить отправкуREADY=1. - Для
oneshotубедиться, что команда должна завершаться. - Для
forkingпроверить завершение родительского процесса и корректностьPIDFile=. - Проверить незавершённые задания и зависимости.
- Проверить итоговую конфигурацию через
systemctl catи синтаксис черезsystemd-analyze verify. - Выполнить
daemon-reload, запустить сервис и подтвердить результат по статусу и журналу.
Ограничения по версиям
Набор свойств, точные промежуточные состояния и отдельные возможности systemd различаются между выпусками дистрибутивов. Для установленной системы приоритет имеют локальные справочные страницы:
man systemd.service
man systemd.unit
man systemctl
man journalctl
man systemd-analyze
man sd_notify
Ссылки ниже ведут на официальную документацию проекта systemd для актуальной опубликованной версии. Она может отличаться от версии systemd в конкретном дистрибутиве.
Источники
- systemd.service — типы сервисов, команды запуска и тайм-ауты
- systemd.unit — зависимости, порядок запуска и состояния юнитов
- systemctl — управление юнитами и просмотр свойств
- journalctl — просмотр журнала systemd
- systemd-analyze — проверка юнитов и анализ цепочки запуска
- sd_notify — протокол уведомления о готовности сервиса