Это не обязательно нужно.
Если C
сервисам нужно дождаться S
готовности, чтобы они могли открыть сокет-соединение с ним, то вообще не обязательно делать это. Скорее, можно воспользоваться преимуществами раннего открытия сокетов прослушивания менеджерами сервисов.
Некоторые системы, в том числе s6 Лорана Берко , мой набор инструментов nosh и systemd, имеют способы, с помощью которых сокет прослушивания можно открыть на ранней стадии, что является самым первым шагом при настройке службы. Все они включают в себя нечто иное, чем служебная программа, открывающая сокет (ы) прослушивания, и служебная программа, когда она вызывается, получая сокеты (ы) прослушивания в качестве уже открытых дескрипторов файла.
В частности, с помощью systemd создается модуль сокета, который определяет сокет прослушивания. systemd открывает модуль сокета и устанавливает его так, чтобы сетевая подсистема ядра прослушивала соединения; и передает его фактической службе в качестве дескриптора открытого файла, когда дело доходит до порождения процесса (ов), которые обрабатывают соединения с сокетом. (Он может сделать это двумя способами, точно так же, как inetd
мог бы, но обсуждение деталей Accept=true
против Accept=false
услуг выходит за рамки этого ответа.)
Важным моментом является то, что не обязательно нужно больше упорядочивать, чем это. Ядро объединяет клиентские соединения в очереди до тех пор, пока сервисная программа не будет инициализирована и не готова принять их и общаться с клиентами.
Когда это происходит, протоколы готовности - это самое главное.
У systemd есть набор протоколов готовности, которые он понимает, указав сервис по сервису с Type=
настройкой в сервисном блоке. Особый интересующий notify
протокол готовности - это протокол готовности. С его помощью systemd сообщается, что он ожидает сообщения от службы, а когда служба готова, она отправляет сообщение, указывающее на готовность. systemd задерживает активацию других сервисов, пока не будет помечена готовность.
Использование этого включает в себя две вещи:
- Модифицируя код
S
так, чтобы он вызывал что-то вроде функции Пьера-Ива Ричарда notify_systemd()
или функции Кэмерона Т Нормана notify_socket()
.
- Настройка сервисного блока для сервиса с помощью
Type=notify
и NotifyAccess=main
.
NotifyAccess=main
Ограничение (это значение по умолчанию), потому что Systemd нужно знать , чтобы игнорировать сообщения от злонамеренных (или просто неисправных) программ, потому что любой процесс в системе может отправлять сообщения в сокет уведомления Systemd'S.
Один из них использует код Пьера-Ива Ритшара или Камерона Т Нормана для предпочтения, поскольку он не исключает возможности использования этого механизма в UbuntuBSD, Debian FreeBSD, реальных FreeBSD, TrueOS, OpenBSD и т. Д .; который исключает код, предоставленный авторами systemd.
Одна из ловушек, которую следует избегать, - это systemd-notify
программа. У него есть несколько основных проблем, не последняя из которых заключается в том, что отправленные с ним сообщения могут в конечном итоге быть отброшенными необработанными systemd. Самая главная проблема в этом случае заключается в том, что он не запускается как «основной» процесс службы, поэтому необходимо открыть уведомления о готовности службы S
для каждого процесса в системе NotifyAccess=all
.
Еще одна ловушка, которую следует избегать, - думать, что forking
протокол проще. Не то. Чтобы сделать это правильно, нужно не разветвляться и не выходить из родительского процесса, пока (с одной стороны) не будут запущены все рабочие потоки программы. Это не соответствует тому, как подавляющее большинство демонов, которые разветвляются, на самом деле разветвляются.
дальнейшее чтение
systemd.service(5)
,NotifyAccess=all
будут приниматься сообщения от всех членов контрольной группы службы , что не подразумевает просто какого-либо мошеннического процесса в системе. Это достаточно безопасно для большинства случаев использования. Кроме того, ваше беспокойство по поводу переносимости в другие операционные системы не имеет отношения к OP, так как мы уже обсуждаем Systemd здесь.Обращаясь к странице справочника
systemd.service(5)
, а именно к разделу о Type = , каждый тип сервиса по-разному определяет, готов ли Systemd предлагать функциональность другим сервисам:Если
Type=simple
его каналы связи должны быть установлены до запуска демона (например, сокеты, установленные systemd, через активацию сокетов).Если
Type=forking
ожидается, что родительский процесс завершится после завершения запуска и настройки всех каналов связи.Если
Type=dbus
ожидается, что демон получит имя на шине D-Bus, после чего systemd продолжит запуск последующих устройств.Если
Type=notify
, ожидается, что демон отправит уведомление черезsd_notify(3)
или эквивалентный вызов, когда он завершит запуск. systemd продолжит запуск последующих модулей после отправки этого уведомления.Для последнего варианта (отправка сообщения через
sd_notify
), вы можете использоватьsystemd-notify
утилиту, и не забудьте предоставить ей доступ с помощьюNotifyAccess=all
.Учитывая, что у вас есть контроль над сервисом
S
, вы можете выбрать лучший вариант для вашего варианта использования или просто тот, который проще всего реализовать.источник
нравится:
S.service
C0.service
C1.service
C9.service
Где / usr / bin / myBinary делает вызов sd_notify READY = 1, когда его инициализация завершена.
В зависимости от того, как вы хотите, чтобы зависимость зависела, вы можете использовать PartOf, Требуется, или BindsTo, или другие .
источник