Причина запуска скрипта после начала работы сети?

Я относительно новичок в системе и изучаю ее архитектуру.

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

Я запускаю Arch, используя systemd, а также netctl.

Чтобы проверить, я написал простой скрипт, который просто выполняет ip addr list > /tmp/ip.txt . Я создал следующий служебный файл для этого скрипта.

 (/etc/systemd/system/test.service) [Unit] Description=test service [Service] ExecStart=/root/test.script [Install] WantedBy=multi-user.target 

Затем я включил скрипт,

 systemctl enable test 

После перезапуска сценарий действительно запускается, но он запускается до запуска сети. Другими словами, на выходе в ip.txt отображается адрес IPv4, назначенный для основного интерфейса. К моменту входа в систему адрес IPv4 действительно был назначен, а работа в сети.

Я предполагаю, что могу изменить точку, в которой работает скрипт, возиться с параметром WantedBy , но я не уверен, как это сделать.

Может ли кто-нибудь указать мне в правильном направлении?

В системных зависимостях конфигурации сети

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

Настройка службы

В текущих системах заказ после network.target просто гарантирует, что сетевая услуга запущена, а не какая-то фактическая конфигурация. Вы должны заказать после network-online.target и потянуть его, чтобы добиться этого.

 [Unit] Wants=network-online.target After=network-online.target 

Для совместимости со старыми системами вам может потребоваться заказать и после network.target.

 [Unit] Wants=network-online.target After=network.target network-online.target 

Это для единичного файла вашего сервиса и для systemd.

Реализация в текущих версиях программного обеспечения

Теперь вам нужно убедиться, что network-online.target работает должным образом (или, по крайней мере, вы можете использовать network.target ).

Текущая версия NetworkManager предлагает NetworkManager-wait-online.service который извлекается через network-online.target и, следовательно, вашим сервисом. Эта специальная услуга гарантирует, что ваш сервис будет ждать, пока все подключенные конфигурации, которые будут запущены автоматически, будут успешными, неудачными или тайм-аутами.

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

Для полноты, служба /etc/init.d/network в Fedora, интерпретируемая текущими версиями systemd, блокирует network.target и, таким образом, косвенно блокирует network-online.target и вашу службу. Это пример реализации на основе скриптов.

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

Вы можете проверить, работает ли netctl одинаково, и эта информация станет ценным дополнением к этому ответу.

Реализации в более старых версиях программного обеспечения

Я не думаю, что вы увидите достаточно старую версию systemd, где это не сработает. Но вы можете проверить, что по крайней мере network-online.target существует и что он упорядочивается после network.target .

Ранее NetworkManager гарантировал, что по крайней мере одно соединение будет применяться. И даже для того, чтобы работать, вам нужно будет включить NetworkManager-wait-online.service явно. Это было давно зафиксировано в Fedora, но недавно было применено вверх по течению.

 systemctl enable NetworkManager-wait-online.service 

Замечания по реализациям network.target и network-online.target

Вам никогда не придется заставлять ваше программное обеспечение зависеть от NetworkManager.service или NetworkManager-wait-online.service или каких-либо других конкретных сервисов. Вместо этого все службы управления сетью должны заказывать себя перед network.target и, возможно, network-online.target .

Простая служба управления сетью, основанная на сценарии, должна завершить настройку сети до выхода из системы и должна сама заказать ее перед network.target и, таким образом, косвенно перед network-online.target .

 [Unit] Before=network.target [Service] Type=oneshot ExecStart=... RemainAfterExit=yes 

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

 [Unit] Before=network.target [Service] Type=simple ExecStart=... 

Служба, ожидающая завершения демона, должна заказывать себя после конкретной службы и перед network-online.target . Он должен использовать Requisite для службы демона, чтобы он не срабатывал немедленно, если соответствующая служба управления сетью не используется.

 [Unit] Requisite=... After=... Before=network-online.target [Service] Type=oneshot ExecStart=... RemainAfterExit=yes 

Пакет должен установить символическую ссылку на службу ожидания в каталоге wants для network-online.target чтобы она зависала от служб, которые хотят дождаться настроенной сети.

 ln -s /usr/lib/systemd/system/... /usr/lib/systemd/system/network-online.target.wants/ 

Связанная документация

Итоговые заметки

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

Вы можете использовать After в разделе [Unit] чтобы определить службу, которая должна быть запущена до запуска вашего сервиса. Например, если вы используете NetworkManager, вы можете запустить свою службу после запуска NetworkManager.

 [Unit] Description=test service After=NetworkManager.service 

Если ваша служба предоставляет сервер, который может пассивно ждать, когда кто-то подключится к нему, используйте это:

 [Unit] After=network.target 

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

Если ваша служба действует как клиент или сверстна, это более уместно:

 [Unit] After=network-online.target Requires=network-online.target того, как [Unit] After=network-online.target Requires=network-online.target 

До systemd 213 network-online.target необходимо обходное решение Pavel (вам нужно вручную включить службу, которая будет ждать, пока сеть будет работать). Начиная с systemd 213 это делается по умолчанию. systemd-networkd-wait-online будет ожидать, что по крайней мере один адрес (как маршрутизируемый, так и link-local) будет настроен на интерфейс без петли.

Конфигурирование systemd-networkd, NetworkManager или эквивалент – это самостоятельная задача. DHCP (для IPv4) и NDP (для IPv6) имеют тенденцию работать из коробки, но вы должны настроить их так, чтобы ваше точное определение «сеть вверх» – это то, что запускает network-online.target .

Документация:

  • network.target
  • network-online.target
  • Выполнение сервисов после завершения работы сети

Я предполагаю, что могу изменить точку, в которой работает скрипт, возиться с параметром WantedBy

Это будет иметь противоположный эффект от того, что вы хотите. От man systemd.unit :

WantedBy =, RequiredBy =

[…] Символьная ссылка создается в каталоге .wants / или .requires / каждого из перечисленных единиц, когда это устройство установлено с помощью разрешения systemctl. Это приводит к тому, что зависимость типа Wants = или Requires = добавляется от указанного блока к текущему устройству .

Исходя из этого, мы можем видеть, что подходящий вариант единицы – «Хочет» или «Требует»; основанный на их описании, «Requires», вероятно, правильный, с добавлением «После», чтобы гарантировать, что не только сетевая служба будет запущена, но и запущена до этого устройства.

Ни один из вариантов устройства, AFAIK, не может включать в себя условие, что начальный perquisite должен быть завершен или достиг определенной точки (сеть, вероятно, является службой демона), только сначала она начинается . Имея это в виду, вы можете захотеть сделать свой скрипт Type=forking и заблаговременно задержать (например, 30 секунд) или какой-то цикл выхода на успех, включая задержку, чтобы убедиться, что у вас есть DHCP аренда сначала.

Используйте After в разделе [Unit] чтобы указать, что должно быть запущено перед вашим собственным сервисом. (Эта часть предыдущего ответа верна.)

Чтобы запустить службу после того, как сеть встала, используйте сетевой объект, который должен применяться, если вы используете NetworkManager, систему conf.d / netctl в Arch или какую-либо другую службу, о которой система знает.

 [Unit] #..... After=network.target 

Краткий обзор подтвердит, что каждая другая служба вашей системы, которая полагается на сетевое подключение, содержит эту директиву.

Он также переносится на любой дистрибутив, в котором используется systemd. Ваш файл подразделения будет таким же для Arch, Fedora, RHEL 7, будущих версий Debian …


Службы, которые запускают сетевое подключение, такие как скрипты Arch или ваши собственные, должны указывать это в своих собственных файлах модулей.

 [Unit] Wants=network.target Before=network.target 

Я хотел добавить пункт к этой статье. В настоящее время (летом 2015 г.) в RHEL7 / CentOS 7, network-online.target неправильно задан до того, как сеть IPv6 завершена, поэтому демоны, которые имеют

 Wants=network-online.target After=network-online.target 

в определении службы, которые также явно привязаны к адресам IPv6, вероятно, будут запущены до запуска и запуска IPv6, в результате чего они будут терпеть неудачу.

 [Unit] After=systemd-networkd.service 

работает на меня.