1

Я пытаюсь вызвать iptables-restore в сценарии systemd.service. У меня есть несколько правил, которые требуют поиска DNS. Я включил After = bind9.service в раздел Unit для брандмауэра. Однако systemd считает, что bind9 запускается, когда он разветвляется, а не когда named готов к обслуживанию запросов. Он запускает iptables-restore до того, как сможет разрешить имя хоста, и поэтому завершается неудачно. Вот соответствующий раздел системного журнала:

Dec 13 21:29:02 fw systemd[1]: Started BIND Domain Name Server.
Dec 13 21:29:02 fw systemd[1]: Reached target Host and Network Name Lookups.
Dec 13 21:29:02 fw systemd[1]: Starting Load iptables Rules...
Dec 13 21:29:02 fw systemd[1]: Started Homebridge HomeKit bridge.
Dec 13 21:29:02 fw systemd[1]: Starting OpenBSD Secure Shell server...
Dec 13 21:29:02 fw sh[1841]: iptables-restore v1.6.0: host/network `example.com' not found
Dec 13 21:29:02 fw sh[1841]: Error occurred at line: 24
Dec 13 21:29:02 fw sh[1841]: Try `iptables-restore -h' or 'iptables-restore --help' for more information.
Dec 13 21:29:02 fw named[1838]: starting BIND 9.10.3-P4-Ubuntu <id:ebd72b3> -f -4 -u bind

Вот служебный файл:

[Unit]
Description=Load iptables Rules
After=bind9.service

[Install]
WantedBy=multi-user.target
WantedBy=network-online.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/sh -c "/sbin/iptables-restore < /etc/iptables.up.rules"

Как лучше всего выполнить команду iptables-restore при загрузке, но подождать, пока named будет активным?

1 ответ1

2

Однако systemd считает, что bind9 запускается, когда он разветвляется, а не когда named готов к обслуживанию запросов.

У Systemd нет другого способа узнать, когда named "готов к обслуживанию запросов". Общепринятый протокол, восходящий к дням SysVinit, заключается в том, что демон разветвляется, все настраивает и, как только он готов, сообщает своему родителю, что он может теперь выйти (обычно через канал или сигнал). Это просто и даже работает, если ваш init - простой shell-скрипт: named; echo Ready!

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

Также возможны и другие протоколы - например, если используется Type = notify, то демон должен отправить сообщение READY = 1; с Type = dbus он должен требовать имя на системной шине; и т.п.

Но если named не реализует этот протокол правильно - то есть, если его начальный процесс завершается слишком рано после разветвления - тогда init ничего не может с этим поделать. Это не работа инициатора иметь дело с демонами, которые лгут ему (из-за некомпетентности или иным образом).

Сказав это, первое, что нужно сделать, это проверить, как на самом деле работает bind9.service . Вполне возможно, что он запускается не по имени, а через слои сценариев init.d, что, как правило, вызывает аналогичные проблемы. (Даже при том, что журналы не показывают типичный префикс «LSB:…», который я все равно проверю.)

Может также случиться так, что bind9.service был изменен на Type = simple, который вообще не поддерживает никаких уведомлений о готовности! Это также часто случается, когда сопровождающий вслепую замечает, что systemd говорит, что разветвление - это зло, с какого-то сайта.

Поэтому убедитесь, что bind9.service на самом деле Type = forking (не Type = simple) и что он запускается по имени напрямую (и с необходимыми опциями «пожалуйста, демонизируйте»).

Если это не сработает (т. Е. Named по-прежнему демонизируется слишком рано), вы можете использовать только второй сервис, который продолжает проверять доступность DNS.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .