Назад | Перейти на главную страницу

Набор сервисов systemd, требующих общей фазы инициализации?

В 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

Но когда я пытаюсь запустить их, мне не удается сделать то, что я хочу:

  1. sudo systemctl start svc-init
    • он правильно останавливает svc-a и svc-b
    • но это не так Начало svc-a и svc-b снова после завершения svc-init
  2. sudo systemctl start svc-a
    • он не заставляет svc-init запускаться заранее
  3. sudo systemctl start svc-a svc-b svc-init
    • эффект кажется таким же, как в (1) выше (то есть, ... start svc-init)
  4. sudo systemctl start svc-init svc-a svc-b
    • не запускает svc-init
    • печатает: Job for svc-init.service canceled.

Какие волшебные заклинания systemd заставляют систему вести себя так, как мне нужно? Или мне нужно как-то иначе структурировать единицы?

редактировать: По предложению в комментариях: чтобы уточнить, svc-a и svc-b в моем случае на самом деле являются экземплярами одной службы и, возможно, необходимо динамически запускать / останавливать (на самом деле они: svc@1, svc@2, svc@3, и т.д.).

Обсуждать Systemd может быть сложно, но это похоже на хороший эксперимент:

svc-init.service

[Unit]
Before=svc@.service

Before сообщает systemd, что svc-init должен быть полностью выполнен до того, как будет запущена любая именованная служба. Это должно дать вам ваш явный обязательный заказ.

svc @ .service

[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