“сценарный” триггерный блок в systemd

Вопрос или проблема

Я пытаюсь найти концепцию в systemd (если она существует), которая позволяет внешнему скрипту вызывать или уведомлять о синтетическом изменении состояния, от которого могут зависеть другие юниты для запуска/остановки их включенных сервисов.

Рассмотрим в качестве примера NetworkManager (понимая, что может уже существовать нативный подход systemd для этого, и игнорируя systemd-networkd на данный момент): NM имеет директорию dispatcher.d, где я могу установить скрипт, который запускается при старте или остановке подключений.

Если я хочу, чтобы systemd-сервис запускался при конкретном подключении и останавливался при его остановке, я мог бы явно создать (непроверенный) скрипт…

if [ "$CONNECTION_ID" = "The connection" ]; then 
  [ "$NM_DISPATCHER_ACTION" = "up" ]   && systemctl start the.service
  [ "$NM_DISPATCHER_ACTION" = "down" ] && systemctl stop the.service
fi

…но я бы предпочел скриптовать это для (псевдо) systemctl activate the.trigger и systemctl deactivate the.trigger, чтобы я мог управлять рядом юнитов (сервисов, маунтов и т. д., включая юниты --user) за один раз.

(Возможно, я также смог бы расширить вышеизложенное до [email protected], так что имя подключения могло бы быть вынесено в наружу скрипта.)

Я рассматривал возможность использования таймера, но хотел бы чего-то более событийно-ориентированного, чем опрос nmcli connection show --active | grep "The connection".

(Пример выше является специфическим, но я также интересуюсь общей идиомой. Я готов провести дополнительное исследование, мне просто не хватает номенклатуры.)

Существует ли в systemd идиоматическая концепция для того, что я пытаюсь сделать, и если да, можете ли вы предоставить пример юнита?

Ответ или решение

Система инициализации systemd является мощным инструментом для управления службами и ресурсами в операционных системах на основе Linux. Она предоставляет возможность организовать гибкую систему инициализации, управления зависимостями и мониторинга. Одной из ключевых концепций systemd является возможность создавать "триггерные" юниты, которые могут быть активированы внешними событиями, как, например, запуск скрипта. Это позволяет системным администраторам широко настраивать поведения системы в ответ на различные события.

Теория

Основная идея состоит в создании юнита, который может реагировать на внешние триггеры. Этот метод позволяет использовать systemd как механизм для управления состояниями на основе событий. Например, в случае с NetworkManager можно воспользоваться папкой dispatcher.d для выполнения действий при изменении состояния подключения. Однако реализация такого взаимодействия при помощи стандартных системных служб systemd может быть более эффективной за счет использования механизмов, подобных состоянию инстанса, Path и Socket юнитов или использования команд user-defined systemctl.

Понятия и функции systemd

  1. Target Units: Юниты типа target могут быть использованы для создания синтетических точек состояния системы. Они позволяют организовать зависимости между службами и другими юнитами.

  2. Path и Socket Units: Эти юниты могут служить в качестве триггера для активации других юнитов. Path юниты отслеживают изменения в файловой системе, тогда как Socket юниты могут слушать сетевые соединения.

  3. Custom Services: Создание кастомных сервисов, которые могут быть запущены или остановлены при возникновении определенных условий, заданных во внешнем скрипте.

  4. Environment Files: Использование служебных файлов окружения для передачи параметров и переменных в юниты systemd.

Пример

Рассмотрим создание системного юнита, который будет реагировать на изменения состояния подключения. Предположим, у нас есть скрипт, обрабатывающий событие изменения состояния в NetworkManager и вызывающий systemctl для управления нашим кастомным триггером.

1. script.service

Создадим сервис, который будет обрабатываться нашим скриптом.

[Unit]
Description=Custom Script Service
ConditionPathExists=/path/to/custom/script.sh

[Service]
Type=oneshot
ExecStart=/path/to/custom/script.sh
RemainAfterExit=yes

2. network-trigger.target

Создадим целевой юнит, который будет служить точкой активации для других юнитов.

[Unit]
Description=Network Trigger Target
Requires=network-online.target
After=network-online.target

[Install]
WantedBy=multi-user.target

3. Скрипт диспетчеризации

Этот скрипт будет взаимодействовать с NetworkManager и активировать наш целевой юнит при наступлении определенного события.

#!/bin/bash

if [ "$NM_DISPATCHER_ACTION" = "up" ] && [ "$CONNECTION_ID" = "SpecificConnection" ]; then
    systemctl start network-trigger.target
elif [ "$NM_DISPATCHER_ACTION" = "down" ]; then
    systemctl stop network-trigger.target
fi

Применение

Использование подобного подхода позволяет вам устанавливать зависимости для других служб или юнитов от вашего таргета network-trigger.target. Например, можно настроить службу example.service, которая будет запускаться и останавливаться в зависимости от состояния network-trigger.target.

[Unit]
Description=Example Service
BindsTo=network-trigger.target
After=network-trigger.target

[Service]
ExecStart=/usr/bin/example-daemon
ExecStop=/usr/bin/stop-example-daemon

Заключение

Используя systemd, можно создать сложную систему взаимодействия между службами и событиями, ускорив реагирование системы на изменения внешнего окружения. Это позволяет не только оптимизировать процесс управления сервисами, но и упрощает администрирование, особенно на серверных системах с высоким уровнем динамичности подключений и ресурсов. Таким образом, подход с использованием триггеров и таргетов, управляемых скриптами, является не только возможным, но и весьма мощным решением.

Оцените материал
Добавить комментарий

Капча загружается...