系统生成和进程生成


14

通常不要在这里发布信息,但是我正在把头发撕掉。我有一个Python脚本,它在启动时会分叉,并负责启动其他一系列进程。该脚本曾经在启动时通过sysvinit启动,但是最近我升级到Debian Jessie,因此对其进行了修改,使其可以通过systemd启动。

不幸的是,我遇到了一个我无法解决的问题。当您直接在用户外壳程序中启动脚本时,它将正确启动其子进程,并且当脚本退出时,子进程将被孤立并继续运行。

通过systemd启动时,如果父进程退出,则子进程也全部退出(嗯,它们在其中启动的Screen消失并显示为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屏幕中启动和停止服务器。它通常一直在运行,不会生成服务并退出。但是在某些情况下,我希望能够在不终止子进程的情况下重新加载脚本,即使这意味着这些进程被孤立为pid1。实际上,即使Python脚本以如下方式启动进程也没有关系:父进程,如果可能的话。

关于其工作原理的更好解释:

  • Systemd产生/Server.py
  • Server.py分叉并为Systemd写入pid文件
  • 然后,Server.py根据其指示在gnu屏幕中生成服务器进程
  • Server.py继续运行以执行从服务器请求的任何重新启动

在不使用Systemd的情况下启动时,可以重新启动Server.py,并且启动的gnu屏幕不受影响。使用Systemd启动时,当Server.py关闭时,它们会被杀死,而不是将这些屏幕进程孤立为pid 1。


1
如果没有Server.py代码和启动的服务如何分叉(如果它们分叉)的描述,就很难提供解决方案。但是,一般来说,这是准备协议不匹配的问题。
intelfx 2015年

顺便说一句,ExecStop=不需要。systemd在停止时的默认操作是杀死进程。您可能需要查看KillMode=指令的文档。
intelfx 2015年

1
而且,最后...如果没有适当的准备协议(一simpleforking,实际上),不得已将是Type=oneshotRemainAfterExit=yesKillMode=control-group
intelfx

@intelfx本质上,Python脚本使用Subprocess.call在屏幕中启动服务器。它比这更复杂,因为该脚本从其他地方接收命令,告诉它启动哪个屏幕,不启动哪个屏幕。哪些屏幕可用也是动态的,因此为什么不能凭自己的权利将它们用作系统服务。理想情况下,我根本不希望systemd将这些屏幕作为服务的一部分来处理,但是目前,它们被转储到同一个进程组中,并且如果重新启动,则会与主服务器一起消失。
博茨瓦纳2015年

我的直觉是systemd不会“处理”这样的控制过程(它只是在启动时查找PID,无法识别后面的过程...):|
rogerdpack '19

Answers:


9

我设法通过将KillMode设置为process而不是control-group(默认值)来解决此问题。谢谢大家


尽管这似乎比修复更能解决问题,请参见其他答案...如果执行此操作并执行“ systemctl停止”,则它不会杀死仍将在运行的子进程[?]在systemctl的监督之外?
rogerdpack

5

我有一个Python脚本,它在启动时会分叉,并负责启动其他一系列进程。

这表示您做错了。稍后再进行更多说明。

当脚本退出时,子进程将被孤立并继续运行。

这不是正确的恶魔行为。如果“主”进程(在这种情况下,您已经指定的子进程)Type=forking退出了,则systemd认为该服务已停用,并终止了其他所有仍在运行的进程(在控制组中)以便整理。

有时,从System 5 rc脚本到systemd 的转换并不直接,因为在systemd下执行操作的正确方法大不相同。在systemd中执行(例如)OpenVPN,OpenStack或OSSEC HIDS的正确方法与使用rc脚本执行该操作的方法不同。您拥有分叉的脚本,然后产生了整个孙子进程负载,然后退出以期望这些孙子进程继续运行这一事实表明,您正在产生与相同的恐惧ossec-control,尽管分叉的程度降低了两个。如果您发现自己编写了一个“主”脚本来检查“启用”标志并为系统的“已启用”部分运行子进程,那么您犯的错误与可怕的错误相同ossec-control

systemd不需要这样的本地机制。它已经是服务经理。根据/unix//a/200365/5132,在systemd中执行此操作的正确方法是不要使用一种服务,而该服务会产生一些古怪而混乱的尝试,以拥有“子服务”。它将每个子进程本身作为一个成熟的系统服务。然后,使用正常的systemd控件启用和禁用系统的各个部分,然后启动和停止。如在OSSEC HIDS案例中可以看到的,一个简单的模板服务单元几乎涵盖了所有服务(一个例外是 /ubuntu//a/624871/43344),允许一个服务执行诸如systemctl enable ossec@agentlessd.service启用可选服务之类的操作。agentlessd服务,根本不需要System 5所需要的可怕的“主脚本”机制rc

在很多情况下,这种反思是必要的,可能不像OSSEC HIDS那样极端。像exim和sendmail这样的MTS就是两个。可能只有一个rc脚本可以生成队列运行器,SMTP提交守护程序和SMTP中继守护程序,并在配置文件中带有许多特殊的shell变量来精确控制运行的脚本。但是,使用systemd进行此操作的正确方法是拥有三个适当的服务单元(其中两个具有关联的套接字单元),并且根本没有临时性的东西,只有服务管理器的常规机制即可。


感谢您对此的反馈。尽管我同意拥有子集服务是有道理的,但是出于我无法理解的原因,它是在Python中完成的。我唯一的解决方案是找到一种使该方法起作用的方法。谢谢,不过。我很想正确地做。
博茨瓦纳2015年

脚本启动的“ sub”服务只是作为特定用户在gnu屏幕上运行的服务器。这些服务器发生了很大的变化,有的被添加,有的被删除,并且可以在其他地方进行控制,因此它们实际上并不是systemd中的实际服务,因为这增加了很多复杂性,并且无法集中管理。同样,非系统服务器上也使用相同的脚本。
博茨瓦纳2015年

systemd具有显式功能,无需根访问权限即可添加和删除服务。“还用于非系统服务”是上面唯一的论点之一,无法通过添加更多systemd来解决……好吧,可以说,即使是也可以。:)
查尔斯·达菲

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.