Служба не запускается вместе с зависимостью
Порядок и необходимость в systemd задаются разными параметрами. After= только выстраивает очередь, но никого не запускает. Если зависимость не поднята, служба стартует без неё — и падает на первом обращении.
Вероятные причины
По порядку: сверху то, что встречается чаще.
-
Указан только порядок
After=postgresql.serviceбезWants=илиRequires=не запускает базу. Если она не в автозапуске, приложение стартует раньше и не находит её. -
Зависимость не включена в автозапуск
Даже при
Wants=служба запустится вместе с вашей только при обращении. Если её не включили, при загрузке она может не подняться первой. -
Приложение не умеет ждать
Даже правильные зависимости не гарантируют, что база успела принять соединения: она может быть активной и ещё не готовой.
Диагностика
Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.
Что именно объявлено в unit-файле.
systemctl show myapp.service -p After -p Wants -p RequiresДерево зависимостей с состояниями.
systemctl list-dependencies myapp.service --no-pager | head -20Порядок событий при загрузке: кто когда стартовал.
journalctl -b -u myapp.service -u postgresql.service --no-pager | head -30Решение
Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.
- Почему происходит
After=postgresql.serviceбезWants=илиRequires=не запускает базу. Если она не в автозапуске, приложение стартует раньше и не находит её.
- Как проверить
-
Посмотрите зависимости службы.
systemctl show myapp.service -p After -p Wants -p Requires
- Как исправить
-
Добавьте
Wants=(мягкая) илиRequires=(жёсткая) вместе сAfter=.[Unit] Wants=postgresql.service After=postgresql.service
- Почему происходит
- Даже при
Wants=служба запустится вместе с вашей только при обращении. Если её не включили, при загрузке она может не подняться первой.
- Как проверить
-
Посмотрите состояние включения зависимости.
systemctl is-enabled postgresql.service
- Как исправить
- Включите зависимость в автозапуск: это надёжнее, чем полагаться на мягкую связь.
- Почему происходит
- Даже правильные зависимости не гарантируют, что база успела принять соединения: она может быть активной и ещё не готовой.
- Как проверить
-
Посмотрите, что делает приложение при недоступной зависимости.
journalctl -u myapp.service -b --no-pager | head -20
- Как исправить
-
Добавьте в приложение повторные попытки подключения и
Restart=on-failureс паузой. Это устойчивее любых зависимостей.
Пример вывода
Порядок объявлен, необходимость — нет. Пример показательный: он собран на тестовой машине специально для этой страницы, а не взят из чужого журнала.
$ systemctl show myapp.service -p After -p Wants -p Requires
After=postgresql.service systemd-journald.socket basic.target sysinit.target
Wants=
Requires=
$ journalctl -b -u myapp.service | head -3
myapp[1200]: fatal: dial tcp 127.0.0.1:5432: connect: connection refused
Связанные ошибки
- Dependency failed for … и результат 'dependency' Сообщение Dependency failed for: служба не запускалась, потому что упала её зависимость. Как найти настоящего виновника.
- Connection refused в журнале службы Соединение отклонено: служба не может подключиться к базе, кешу или другому сервису. Порядок запуска, адрес, брандмауэр.
- Цель не достигнута: служба ждёт target, который не наступает Служба не запускается, потому что не достигнута цель из After= или Requires=. Разбор целей multi-user, network-online, graphical.
- Found ordering cycle: циклическая зависимость при загрузке systemd нашёл цикл в порядке запуска и разорвал его, отбросив одну зависимость. Как найти цикл и правильно расставить After и Requires.
- A start job is running: загрузка висит на одной службе Загрузка останавливается с обратным отсчётом: служба не укладывается в таймаут. Как найти виновника и не ждать.
- Address already in use при запуске службы Порт или адрес уже занят: bind() failed (98: Address already in use). Как найти владельца порта и что делать с остатками прежнего процесса.
- Apache: Invalid command — не включён модуль Apache не запускается: директива требует модуль, который не подключён. Как найти нужный модуль и включить.
- Cannot assign requested address при привязке Ошибка 99 при привязке: адрес не принадлежит машине или ещё не поднят. Разбор с network-online.target и ip_nonlocal_bind.
Где встречается чаще всего
Источники
-
systemd.unit(5)
After=, Wants=, Requires= и разница между порядком и требованием. -
Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
Воспроизведено связкой приложения и базы без Wants=.