Задача:
У вас есть два systemd-сервиса:
backend.service и database.service.В юните
backend.service вы прописали:
[Unit]
Requires=database.service
After=database.service
Но после перезагрузки системы
backend.service запускается, хотя `database.service` не стартовал (из-за ошибки).Вопрос:
Почему
backend не дождался базы данных и не остановился вместе с ней, несмотря на Requires=database.service?Подсказка: это не баг systemd. Это особенность.
Правильный ответ:
Потому что
Requires и After действуют только при запуске backend вручную или через systemctl, но не при автоматическом старте на boot, если backend стартует по WantedBy=multi-user.target.🔍 Разбор
-
Requires=database.service говорит: если запускается backend, то systemd должен также запустить database. Но если
database не стартует — backend всё равно может попытаться запуститься.-
After=database.service определяет порядок запуска, но не делает зависимость "жёсткой".- При старте системы systemd может параллельно запускать сервисы, если
backend привязан напрямую к multi-user.target и не указан как зависимость в database.service.✅ Как правильно:
Чтобы
backend не запускался без базы:1. Убедитесь, что
database.service:- прописан как
WantedBy=multi-user.target- и запускается первым
2. Убедитесь, что
backend.service содержит:
[Unit]
Requires=database.service
After=database.service
StartLimitIntervalSec=0
3. И желательно добавить `PartOf=database.service`, если хотите, чтобы backend выключался вместе с базой.
⚠️ Вывод:
- В systemd порядок и тип зависимостей — неочевидны.
- Даже
Requires не гарантирует, что другой сервис успешно работает — только то, что systemd *попробует* его запустить. - Хотите быть уверены — используйте
Condition*, ExecStartPre с проверками или HealthCheck в Docker/K8s.📌 systemd — мощный, но коварный. Не доверяй поверхностной логике — тестируй руками каждую зависимость.