当Python脚本作为系统服务运行时,无法将SIGINT发送到子进程

时间:2020-02-03 01:08:19

标签: python linux systemd

背景

我有一个C#程序,我在Linux(特别是Raspbian)的Mono下运行。我正在研究一个Python脚本,该脚本启动该程序,对其进行监视并优雅地将其杀死。我使用subprocess.Popen在mono下运行C#程序。当我正常运行Python时,我可以向进程发送一个SIGINT,我可以看到它收到了它,并在退出之前很好地清理了自己。

问题: 我希望能够将脚本作为SystemD服务运行,因此我创建了一个简单的SystemD服务文件。现在,C#不再正常退出,而是像发送SIGKILL而不是发送SIGINT一样立即终止。

这是我当前用于解决此问题的简单测试代码:

import os
import signal
import time
import subprocess

call = ['mono', '/home/user/test.exe'] # (not the actual name of the program, changed for this post)

print('starting')
process = subprocess.Popen(call)

time.sleep(20)
print('sending term')
process.send_signal(signal.SIGINT)
print('term sent')

这是我的SystemD服务文件(将我的实际用户名更改为“用户”):

[Unit]
Description=Test
After=multi-user.target

[Service]
User=user
Group=user
WorkingDirectory=/home/user/testcode
Type=simple
ExecStart=/home/user/testcode/.venv/bin/python /home/user/testcode/test.py
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=testcode

[Install]
WantedBy=multi-user.target

我尝试观察HTOP,以了解Mono进程的PID和GID是否发生任何奇怪的事情,但是在直接启动和SystemD启动的Python脚本之间看起来或多或少都是相同的。

不幸的是,Mono程序对我来说有点像个黑匣子,所以我对其中发生的事情知之甚少。我确实可以访问源代码,但是我没有C#的经验,也不知道从哪里开始寻找线索。我能够判断它是否正常退出,因为它会生成一个我可以tail的日志文件,并在正常退出时打印出几行。强制终止时,这些行不会被打印。

我尝试过的事情 我主要尝试了使用Popen.

来启动程序的不同方法
  • 使用shell=True会使C#程序在正常启动时根本不会停止,但是在通过SystemD启动时,它表现出与没有shell=True时相同的非优雅退出行为。
  • 我尝试了此thread的一些建议,即从第一个答案开始使用preexec_fn=os.setsidos.killpg(os.getpgid(pro.pid), signal.SIGTERM),有无shell=True时没有运气。正常启动和SystemD启动都显示非正常退出。
  • 我在脚本的末尾添加了time.sleep(5),以使C#有时间在脚本退出之前退出。没变化。我的想法是SystemD看到Python脚本退出,并清理了它产生的所有其他进程,然后才有机会正常退出。

0 个答案:

没有答案