Обычно не пишите здесь, но я вырываю свои волосы из-за этого. У меня есть скрипт Python, который разветвляется при запуске и отвечает за запуск нескольких других процессов. Этот скрипт запускался при запуске через sysvinit, но недавно я обновился до Debian Jessie, поэтому адаптировал его для запуска через systemd.
К сожалению, я сталкиваюсь с проблемой, которую не могу решить. Когда вы запускаете сценарий непосредственно в пользовательской оболочке, он правильно запускает свои дочерние процессы, а при выходе из сценария дочерние процессы становятся сиротами и продолжают выполняться.
Когда запускается через systemd, если родительский процесс завершается, все дети тоже выходят (ну, экраны, которые они запускают в die и выглядят как Dead ???)
В идеале мне нужно иметь возможность перезапустить родительский скрипт, не убивая все дочерние процессы, есть что-то, чего мне не хватает?
Благодарность!
[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 запускает процессы как родительский процесс, если это вообще возможно.
Лучшее объяснение того, как это работает:
- Systemd порождает /Server.py
- Server.py разветвляется и записывает pid-файл для Systemd
- Затем Server.py порождает процессы сервера в окне GNU в соответствии с его инструкциями
- Server.py продолжает работать, чтобы выполнить любые перезапуски, запрошенные с сервера
При запуске без Systemd Server.py может быть перезапущен, и экраны gnu, которые он запускает, не затрагиваются. При запуске с Systemd, когда Server.py завершает работу, вместо тех экранных процессов, которые отключены от pid 1, они уничтожаются.
источник
Server.py
кода и описания того, как запускаются запущенные сервисы (если они работают). Однако, вообще говоря, это проблема несоответствия протокола готовности .ExecStop=
это не нужно. Действие systemd по умолчанию при остановке - уничтожение процессов. Вы можете взглянуть на документацию дляKillMode=
директивы.simple
илиforking
, собственно), последним средством будетType=oneshot
,RemainAfterExit=yes
иKillMode=control-group
.Ответы:
Мне удалось это исправить, просто установив KillMode для обработки вместо control-group (по умолчанию). Спасибо всем
источник
Что указывает на то, что вы делаете это неправильно. Подробнее об этом через минуту.
Это не правильное поведение демона. Если «основной» процесс - в данном случае дочерний элемент, который вы разветвили, поскольку вы указали это
Type=forking
- завершается, systemd считает, что служба деактивирована, и завершает любые другие все еще работающие процессы (в контрольной группе), чтобы привести в порядок ,Иногда преобразование из
rc
сценариев System 5 в systemd не является простым, потому что правильный подход к работе под systemd совсем другой. Правильный способ сделать (скажем) OpenVPN или OpenStack или OSSEC HIDS в Systemd не то же самое , как можно было бы сделать это с помощьюrc
сценария. Тот факт, что у вас есть скрипт, который разветвляется, затем порождает целую нагрузку процессов внуков, а затем ожидает, что эти внуки продолжат работать, указывает на то, что вы совершаете тот же ужас, что иossec-control
, хотя и с двумя уровнями разветвления. Если вы обнаружите, что пишете «главный» сценарий, который проверяет флаги «enable» и запускает дочерние процессы для «включенных» частей вашей системы, то вы совершаете ту же ошибку, что и ужасныеossec-control
.С systemd такие доморощенные механизмы не нужны. Это уже менеджер сервиса. Согласно /unix//a/200365/5132 , правильный способ сделать это в systemd - это не иметь один сервис, который порождает какую-то дурацкую и запутанную попытку иметь «подуслуги». Это означает, что каждый дочерний процесс является полноценной системной службой по отдельности. Затем один включает и отключает, а также запускает и останавливает различные части системы, используя обычные средства управления systemd. Как вы можете видеть в случае OSSEC HIDS, простой шаблонный сервисный блок покрывает почти все (одно исключение на /ubuntu//a/624871/43344 ) сервисы, позволяя делать такие вещи, как
systemctl enable ossec@agentlessd.service
включение дополнительногоagentlessd
сервис, без какой-либо необходимости в ужасающем механизме «главного сценария», который был необходим в System 5rc
.Есть много случаев, возможно, не таких экстремальных, как OSSEC HIDS, где такое переосмысление необходимо. МТС, такие как exim и sendmail, два таких. Можно было бы иметь один
rc
сценарий, который порождает обработчик очереди, демон отправки SMTP и демон ретрансляции SMTP, с кучей специальных переменных оболочки в файле конфигурации, чтобы точно контролировать, какие из них запускаются. Но правильный способ сделать это с помощью systemd - это иметь три надлежащих сервисных модуля (два из которых имеют связанные сокетные блоки ) и никаких специальных вещей вообще, только обычные механизмы менеджера сервисов.источник
Вы можете просто спать с родителем и ждать, пока systemd убьет его во время остановки.
источник