Системний і нерестовий процес


14

Зазвичай не публікуйте тут, але я розриваю волосся над цим. У мене є скрипт Python, який розщеплюється під час його запуску і відповідає за запуск ряду інших процесів. Цей сценарій запускався при запуску через sysvinit, але нещодавно я перейшов до Debian Jessie, тому адаптував його до запуску через systemd.

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

Коли запускається Via systemd, якщо вихідний процес закінчується, діти теж виходять (ну, екран, який вони запускають у мертвій формі і виглядають як мертвий ???)

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

Спасибі!

[Unit]
Description=Server commander
After=network.target

[Service]
User=serveruser
Type=forking
PIDFile=/var/Server/Server.pid

ExecStart=/var/Server/Server.py
ExecStop=/bin/kill -s TERM $MAINPID

[Install]
WantedBy=multi-user.target

Редагувати: Мабуть, для мене важливо зазначити, що скрипт Python по суті є «контролером» для його дочірніх процесів. Він запускає та зупиняє сервери на gnu-екранах за запитом центрального сервера. Зазвичай він завжди працює, він не нерестує послуги та не виходить. Однак є випадки, коли я хотів би мати можливість перезавантажити скрипт, не вбиваючи дочірніх процесів, навіть якщо це означає, що процеси осиротіли до pid 1. Насправді, це навіть не мало значення, якщо сценарій Python запустив процеси, як батьківський процес, якщо це навіть можливо.

Краще пояснення, як це працює:

  • Системні нерести /Server.py
  • Server.py розкручується та записує pid-файл для Systemd
  • Потім Server.py породжує серверні процеси на екрані gnu на основі його інструкцій
  • Server.py продовжує працювати для виконання будь-яких перезавантажень, запитаних від сервера

При запуску без Systemd, Server.py можна перезапустити, а на екрани gnu, які він запускає, не впливати. При запуску із Systemd, коли Server.py вимикається, замість того, щоб процеси екрана осиротіли до pid 1, вони вбиваються.


1
Важко надати рішення, не маючи Server.pyкоду та опису того, як розгортаються запущені служби (якщо вони розщеплюються). Однак, загалом кажучи, це проблема невідповідності протоколу готовності .
intelfx

До речі, ExecStop=це не потрібно. Дія за замовчуванням systemd при зупинці полягає в знищенні процесів. Ви можете поглянути на документацію для KillMode=директиви.
intelfx

1
І, нарешті ... Якщо немає відповідного протоколу готовності (один з simpleчи forking, на самом деле), останнього курорт буде Type=oneshot, RemainAfterExit=yesі KillMode=control-group.
intelfx

@intelfx По суті сценарій Python запускає сервер на екрані за допомогою Subprocess.call. Це складніше, ніж це, тому що скрипт отримує команди з інших місць, вказуючи, які екрани починати, а які ні. Які екрани доступні, також є динамічним, тому вони не можуть бути систематизованими службами самостійно. В ідеалі я не хочу, щоб системні трактували ці екрани як частину сервісу взагалі, але наразі вони потрапляють у ту саму групу процесів і гинуть з майстром, якщо її перезапустити.
Боттсвана

Моя думка полягає в тому, що systemd не "обробляє" процес управління таким чином (він просто шукає PID в момент запуску, не розпізнає пізніші ...): |
rogerdpack

Відповіді:


9

Мені вдалося виправити це просто, встановивши KillMode для обробки замість контрольної групи (за замовчуванням). Дякую всім


Це здається чимось обходом, ніж виправленням, хоча дивіться інші відповіді ... якщо ви це зробите і зробите "systemctl stop", то це не вб'є дочірніх процесів, які вони все ще будуть працювати [?] поза наглядом systemctl?
rogerdpack

5

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

Що вказує на те, що ви робите це неправильно. Більше про це за мить.

коли сценарій закінчується, дочірні процеси осиротіли і продовжують працювати.

Це неправильна поведінка dæmon. Якщо "основний" процес - у цьому випадку дитина, яку ви роздвояли, з тих пір, яку ви вказали, Type=forking- виходить, systemd вважає, що служба деактивується та припиняє будь-які інші запущені процеси (у контрольній групі) для того, щоб привести в порядок .

Іноді перетворення з rcсценаріїв System 5 в systemd не є простим, оскільки правильний спосіб робити речі під systemd зовсім інший. Правильний спосіб зробити (скажімо) OpenVPN, або OpenStack, або OSSEC HIDS в systemd - це не той самий, як це можна було б зробити із rcсценарієм. Той факт, що у вас є розгалуження сценарію, а потім нерестування цілого навантаження процесів онуків, а потім очікування того, що ці онуки будуть продовжувати працювати, свідчить про те, що ви вчинили такий самий жах, як ossec-control, хоча і з двома меншими рівнями розщеплення. Якщо ви виявите, що ви пишете "головний" скрипт, який перевіряє "enable" прапори і запускає дочірні процеси для "включених" частин вашої системи, то ви робите ту саму помилку, що і жахлива ossec-control.

Таких механізмів вирощування в домашніх умовах не потрібно. Це вже менеджер служби. Відповідно до /unix//a/200365/5132 , правильний шлях для цього в systemd - це не мати однієї служби, яка породжує деяку нерозумну та заплутану спробу мати "підслужби". Це означає, щоб кожен дочірній процес був повноцінним систематизованим сервісом самостійно. Потім вмикається та вимикається, а також запускається та зупиняється різні частини системи за допомогою звичайних системних елементів керування. Як ви можете бачити у випадку OSSEC HIDS, простий блок обслуговування шаблонів охоплює майже всі (один виняток - за адресою /ubuntu//a/624871/43344 ), що дозволяє робити такі дії, як systemctl enable ossec@agentlessd.serviceувімкнення необов'язковогоagentlessdсервіс, без жодної потреби в жахливому механізмі "головного сценарію", який був потрібний для System 5 rc.

Випадків, мабуть, не настільки екстремальних, як OSSEC HIDS, де таке переосмислення необхідно. Такі MTS, як exim і sendmail, є такими двома. Можливо, був би один rcсценарій, який породжує запуск черги, SMTP Submission dæmon і SMTP Relay dæmon, з купою змінних спеціальних оболонок у файлі конфігурації, щоб контролювати, які саме запускаються. Але правильний спосіб зробити це з systemd - це три належних сервісних одиниці (два з яких мають асоційовані сокетні блоки ) і взагалі відсутні спеціальні речі, а лише звичайні механізми менеджера служби.


Я ціную відгуки про це. Хоча я згоден мати підмножинні послуги має сенс, це було зроблено в Python з тієї причини, в яку я не можу вступити. Моє єдине рішення - знайти спосіб змусити цей метод працювати. Спасибі, хоча. Я хотів би зробити це правильно.
Боттсвана

'Під' сервіси, які запускає скрипт, - це лише сервери, які працюють на gnu-екрані як конкретний користувач. Ці сервери сильно змінюються, деякі додаються, деякі видаляються, і це контролюється в іншому місці, тому вони не можуть бути справжніми сервісами в systemd, тому що це додає великої складності і керувати ним не можна централізовано. Також той самий сценарій використовується і на несистемних серверах.
Боттсвана

systemd має явні засоби, що дозволяють додавати та видаляти служби, не потребуючи кореневого доступу. "Також використовується для несистемних сервісів" - це єдиний аргумент, поданий вище, який неможливо виправити, додавши більше системних ... ну, імовірно, навіть те, що може бути занадто. :)
Чарльз Даффі

0

Ви могли просто спати з батьком і чекати, коли системний вбиє його в час зупинки.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.