Викликати виконання сценарію після запуску мережі?


102

Я відносно новачок у систематизації та вивчаю її архітектуру.

Зараз я намагаюся зрозуміти, як викликати запуск спеціального сценарію оболонки. Цей сценарій потрібно запустити після запуску мережевого шару.

Я запускаю 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параметром, але я не знаю, як це зробити.

Чи міг би хтось вказати на мене у правильному напрямку?

Відповіді:


126

Від системних залежностей від конфігурації мережі

Це дуже легко вплинути на замовлення одиниць системи. З іншого боку, вам слід бути обережними, що гарантує завершений блок.

Налаштуйте свою послугу

У поточних системах замовлення після 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і вашу послугу. Це приклад реалізації на основі сценарію.

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

Ви можете перевірити, чи працює 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

Служба управління мережевою мережевою службою на демонах також повинна замовити себе раніше, network.targetхоча це не дуже корисно.

[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/

Супутня документація

Підсумкові ноти

Я сподіваюся, що я не лише допоміг відповісти на ваше запитання в той момент, коли ви його задали, але також сприяв поліпшенню ситуації в дистрибутиві верхніх потоків і Linux, так що тепер я можу дати кращу відповідь, ніж це було можливо під час написання оригіналу .


Ви маєте на увазі опцію автоматичного підключення, "зачекайте, поки всі з'єднання, налаштовані для запуску, автоматично вдаються"? Чи можу я скористатись цим, коли я встановив параметр "неавтоматично" за замовчуванням = *, але в одному з моїх з'єднань є автоподключение = так? І останнє запитання - я не розумію - очікування для запуску параметр nm-сторінки онлайн та сторінки керівництва не дуже допомагає. Дякуємо за цей запис, високо цінуємо!
lzap

Наскільки я знаю, nm-он-лайн не хвилює no-auto-defaultлише цього auto. У вас є якісь конкретні запитання? На мій погляд, сторінка nm-online чітко зазначає, що з -sнею чекає спробу всіх автоматичних підключень, тобто підключення чи вихід з ладу.
Павло Шимерда

Протягом години возившись з цим лайна, я знайшов рішення: apt-get install sysv-init. :-) Складність, яку systemd додає замість кількох скриптів оболонки, це неприємно.
Хтось

@ Хтось боюсь, що в цій справі написання не є відповідями. Якщо ви використовуєте NetworkManager або будь-який інший інструмент динамічної конфігурації, initscripts не можуть замовити себе після повністю налаштованої мережі. Ви можете отримати обмежену динамічну конфігурацію за допомогою /etc/init.d/networkабо подібного, але це не працює універсально.
Павло Шимерда

@Pavel Šimerda Init виконується серійно, і належний скрипт init не повернеться, доки він не закінчить робити те, на що потрібно розраховувати наступні сценарії. Для роботи в мережі це означатиме, що всі відповідні адаптери будуть готові та готові. Якщо це не просто вдалий термін, НМ поводиться добре в цьому контексті. Справжня проблема, звичайно, полягає в тому, щоб NM винаходила обробку мережі, а не спиралася на існуючі прості і перевірені структури. Настільно люди, схоже, не мають поняття про небезпеку складності. ;-)
Хтось

9

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

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

BindsToтут не так підходить, оскільки служба є разовою подією, а не постійною послугою (якщо вона також не включає ExecStopфункцію запуску, коли мережа знижується).
goldilocks

видаленоBindsTo
фольс

Ви можете додати щось на заміну BindsTo, хоча, наприклад Requires, якщо ви хочете, щоб послуга запускалася лише в тому випадку, якщо NetworkManager робить це. Afterнасправді цього не роблять - це просто означає, що якщо NM також працює, то запустіть це згодом. Якщо NM не запускається, послуга буде запущена в довільній точці.
goldilocks

4
After = network.target краще, ніж After = NetworkManager.service, оскільки він є більш загальним.
Павло Шімерда

7
Зверніть увагу на те, що задає After=fooбуде НЕ викликати fooблок , щоб почати , якщо він ще не запущений, він буде тільки сказати Systemd , як замовити одиниці , якщо вони обидва почали одночасно . Якщо використовувати або After=fooяк, Wants=fooабо Requires=fooбуде мати ефект, fooякщо він не запущений, а також зробити системне замовлення одиниць правильно.
Еміль Лундберг

8

Якщо ваша служба надає сервер, який може пасивно чекати, коли хтось підключиться до нього, скористайтеся цим:

[Unit]
After=network.target

Ваша послуга повинна прив'язуватися до інтерфейсу підстановки. Якщо він використовує активацію сокета (рекомендується) або якщо він лише локальний, ви можете повністю ігнорувати мережеві цілі.

Якщо ваша служба діє як клієнт, або одноліткові, це більше:

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

До systemd 213 , network-online.target потребує вирішення згаданого Павла (вам потрібно вручну ввімкнути сервіс, який буде чекати, коли мережа запрацює). Станом на systemd 213 це робиться за замовчуванням. systemd-networkd-wait-onlineбуде чекати, коли принаймні одна адреса (або маршрутизована, або локальна посилання) буде налаштована на інтерфейсі, який не підтримує цикл.

Налаштування systemd-networkd, NetworkManager або іншого подібного завдання - незалежне завдання. DHCP (для IPv4) і NDP (для IPv6), як правило, спрацьовують з поля, але ви повинні налаштувати їх так, щоб ваше чітке визначення "мережа працює" - це те, що викликає network-online.target.

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


Цікаво, чому нова відповідь, а не лише невеликі вдосконалення існуючої та (сподіваємось), добре структурованої відповіді.
Павло Шімерда

Перші два посилання Документації наразі не працюють.
Пітер Хансен

Навіщо використовувати Requires замість Want?
Карл Моррісон

4

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

Це матиме протилежний ефект від того, що ви хочете. Від man systemd.unit:

WantedBy =, RequirBy =

[...] Символічне посилання створюється у каталозі .wants / або .requires / кожного з перерахованих одиниць, коли цей блок встановлений systemctl enable. Це призводить до того, що залежність типу Wants = або Requires = додається від переліченої одиниці до поточної одиниці .

Виходячи з цього, ми можемо побачити правильний варіант одиниці - "Хоче" або "Потрібно"; Виходячи з опису цих даних, "Потрібно", ймовірно, правильно, додавши "Після", щоб забезпечити не тільки запуск мережевої служби, але і запуск її перед цим блоком.

Жоден з варіантів підрозділу, AFAIK, не може включати умови, що розпочата умова повинна бути завершена або досягти певної точки (мережа, ймовірно, служба демона), тільки що вона починається спочатку. Зважаючи на це, ви, можливо, захочете зробити свій скрипт Type=forkingі запустити здорову затримку (скажімо, 30 секунд) або якийсь цикл виходу на успіх, включаючи затримку, щоб переконатися, що у вас є оренда DHCP спочатку.


1
Ні WantedBy, ні RequiredBy не впливають на замовлення.
Павло Шімерда

1
@ PavelŠimerda: Тут ніхто не стверджував. Упорядкування, чому я чітко зазначив Afterу поєднанні з Requires"гарантувати не тільки запуск сервісу мережі, але і те, що він працює перед цим блоком".
goldilocks

1
Так, Afterпрацює разом з тим Wantsчи Requiresіншим способом. З іншого боку, явні затримки - це погана звичка в інструментах, що базуються на залежності, особливо коли є чіткий спосіб зачекати, поки мережа не буде налаштована, визначена систематизованою документацією, тому мені доводиться наполягати на зниженні.
Павло Шімерда

3

Використовуйте Afterу [Unit]розділі, щоб вказати, що слід розпочати перед власною службою. (Ця частина попередньої відповіді правильна.)

Щоб розпочати службу після налаштування мережі, використовуйте мережеву ціль, яка повинна застосовуватися, чи використовуєте ви NetworkManager, систему conf.d / netctl в Arch або якусь іншу службу, про яку знає systemd.

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

Короткий огляд підтвердить, що кожна інша служба у вашій системі, яка покладається на підключення до мережі, містить цю директиву.

Він також портативний для будь-якого дистрибутива, який використовує systemd. Ваш файл одиниці буде таким самим для Arch, Fedora, RHEL 7, майбутніх версій Debian ...


Служби, які запускають мережеве з'єднання, такі як скрипти Arch або ваш власний, повинні вказати це у власних файлах одиниць.

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

Мені ця Wantsчастина не дуже подобається, оскільки вона має побічні ефекти на інших пакунках. Подивіться, будь ласка, на мою відповідь.
Павло Шімерда

Просто зрозумів , що Wantsна network.targetце гарна ідея тут.
Павло Шімерда,

ви дійсно хочете використовувати network-online.target. ref
Едвард Торвальдс

1

Я хотів додати пункт до цієї статті. Наразі (літо 2015 р.) У RHEL7 / CentOS 7, мережа-online.target неправильно встановлена ​​до того, як мережа IPv6 буде налаштована, тому демони мають

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

у їхньому сервісному визначенні, яке також явно прив'язується до IPv6-адрес, ймовірно, буде запущено до запуску та запуску IPv6, що призведе до їх відмови.


Я думаю, що це стосується лише автоматичної конфігурації IPv6 на основі ядра, яка все-таки є помилкою. Якщо ви хочете правильно замовити після IPv6, вам обов'язково слід використовувати NetworkManager замість /etc/init.d/network. Якщо ви отримаєте те саме питання навіть з NM, це буде вагомою причиною для подання запиту на функцію. Я не перевіряв RHEL / CentOS, я можу допомогти вам у деталях, якщо вас цікавлять.
Павло Шімерда,

0
[Unit]
After=systemd-networkd.service

працює для мене.


Не впевнений, чи працює він у деяких особливих випадках, але це неправильно з кількох причин. Один з них полягає в тому, що networkdнадає власну послугу / чекайте онлайн /. Увімкнення та замовлення після network-online.target- це правильний шлях із будь-якою послугою, яка це підтримує.
Павло Шімерда
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.