В systemd мне нужно настроить некоторые службы, которые зависят от одной общей службы «инициализации», которая должна завершиться до того, как они будут запущены. Также я хотел бы убедиться, что рабочие службы и служба "инициализации" могут никогда не запускайте одновременно в любое время:
manual
BOOT --. "restart svc" ---.
V V
svc-init |-----| |---------|
svc-a |--------------------------------| |----- - - -
svc-b |--------------------------------| |----- - - -
Я хочу быть уверенным, что службы «включены» (запускаются при загрузке системы); Кроме того, я хотел бы иметь возможность перезапустить все это вручную в любое время, когда мне нужно.
Как я могу это сделать?
Я попробовал настроить важные поля, как показано ниже:
/etc/systemd/system/svc-init.service:
[Service] Type=oneshot ExecStart=/opt/svc/init-svc.sh [Install] WantedBy=multi-user.target
... / svc-a.service, ... / svc-b.service:
[Unit] Wants=svc-init.service After=svc-init.service Conflicts=svc-init.service [Service] Restart=always ExecStart=/opt/svc/svc.sh [Install] WantedBy=multi-user.target
Но когда я пытаюсь запустить их, мне не удается сделать то, что я хочу:
sudo systemctl start svc-init
sudo systemctl start svc-a
sudo systemctl start svc-a svc-b svc-init
... start svc-init
)sudo systemctl start svc-init svc-a svc-b
Job for svc-init.service canceled.
Какие волшебные заклинания systemd заставляют систему вести себя так, как мне нужно? Или мне нужно как-то иначе структурировать единицы?
редактировать: По предложению в комментариях: чтобы уточнить, svc-a и svc-b в моем случае на самом деле являются экземплярами одной службы и, возможно, необходимо динамически запускать / останавливать (на самом деле они: svc@1
, svc@2
, svc@3
, и т.д.).
Обсуждать Systemd может быть сложно, но это похоже на хороший эксперимент:
[Unit]
Before=svc@.service
Before
сообщает systemd, что svc-init должен быть полностью выполнен до того, как будет запущена любая именованная служба. Это должно дать вам ваш явный обязательный заказ.
[Unit]
After=svc-init.service
BindsTo=svc-init.service
After
имитирует Before
в сервисе svc-init, и может быть вам удобнее. Объявление его в обоих местах не является ошибкой и не требуется. Это просто делает ваше намерение явным.
BindsTo
сообщает systemd, что если названная служба остановлена по какой-либо причине, эта тоже остановится. Используя его с After
или Before
декларация гарантирует, что эта остановка произойдет в правильном порядке. В зависимости от ваших потребностей вы можете использовать Requires
вместо того BindsTo
, поскольку Requires
указывает, что остановить эту службу только тогда, когда названная служба явно остановился. Если BindsTo
используется всякий раз, когда svc-init
перезапускается, эта служба также будет перезапущена. Любой из них является более сильной версией Wants
вы перечисляете в своих примерах.
Настроен так, когда svc-init
запускается из остановленного состояния, он будет ждать запуска любого svc
экземпляры до svc-init
завершит запуск (до / после) и сделает это только тогда, когда svc-init
успешно завершает запуск (BindsTo). Как только это будет сделано, тогда любой svc
экземпляры запущены. Если svc-init
дается стоп команда, все svc
экземпляры будут остановлены одновременно с svc-init
(BindsTo). Если svc-init
дается начать сначала команда, svc-init и все зависимые службы будут остановлены, а затем запущены.
Если svc-init
предназначен для запуска с последующим выходом, вам может потребоваться SuccessExitStatus=
декларация в своем Unit
чтобы сообщить systemd, какие коды выхода ожидаются при успешном запуске.
Предполагая, что вы не можете избавиться от скриптов и заставить systemd выполнить всю настройку (что вы почти наверняка сможете, но тот, кто написал скрипты, может не знать, как; кричите на поставщика / разработчика, пока они не узнают), я думаю, вам следует используя только один unit файл для этого.
В одном модульном файле вы запустите сценарий инициализации в ExecStartPre=
вариант. Устройство не запустится, если вызванная здесь программа не завершится успешно. Например, в svc@.service
:
[Service]
Restart=always
ExecStartPre=/opt/svc/init-svc.sh %I
ExecStart=/opt/svc/svc.sh %I
[Install]
WantedBy=multi-user.target