如何终止使用 shell=True 启动的 python 子进程
- 2024-11-21 08:33:00
- admin 原创
- 6
问题描述:
我正在使用以下命令启动子进程:
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
但是,当我尝试使用以下方法杀死它时:
p.terminate()
或者
p.kill()
该命令一直在后台运行,所以我想知道如何才能真正终止该进程。
请注意,当我使用以下命令运行时:
p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)
当发出时它确实成功终止p.terminate()
。
解决方案 1:
使用进程组以便能够向组中的所有进程发送信号。为此,您应该将会话 ID附加到生成的/子进程的父进程(在您的情况下是 shell)。这将使其成为进程的组长。因此,现在,当向进程组长发送信号时,它会被传输到该组的所有子进程。
代码如下:
import os
import signal
import subprocess
# The os.setsid() is passed in the argument preexec_fn so
# it's run after the fork() and before exec() to run the shell.
pro = subprocess.Popen(cmd, stdout=subprocess.PIPE,
shell=True, preexec_fn=os.setsid)
os.killpg(os.getpgid(pro.pid), signal.SIGTERM) # Send the signal to all the process groups
解决方案 2:
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
p.kill()
p.kill()
最终终止 shell 进程并且cmd
仍在运行。
我找到了一个方便的解决方法:
p = subprocess.Popen("exec " + cmd, stdout=subprocess.PIPE, shell=True)
这将导致 cmd 继承 shell 进程,而不是让 shell 启动一个不会被终止的子进程。 p.pid
将是你的 cmd 进程的 id。
p.kill()
应该可以。
但我不知道这会对你的管道产生什么影响。
解决方案 3:
如果你可以使用psutil,那么这个就可以完美地工作:
import subprocess
import psutil
def kill(proc_pid):
process = psutil.Process(proc_pid)
for proc in process.children(recursive=True):
proc.kill()
process.kill()
proc = subprocess.Popen(["infinite_app", "param"], shell=True)
try:
proc.wait(timeout=3)
except subprocess.TimeoutExpired:
kill(proc.pid)
解决方案 4:
我可以用它
from subprocess import Popen
process = Popen(command, shell=True)
Popen("TASKKILL /F /PID {pid} /T".format(pid=process.pid))
它杀死了cmd.exe
我所命令的程序。
(在 Windows 上)
解决方案 5:
当shell=True
shell 是子进程,而命令是其子进程时。因此,任何SIGTERM
或SIGKILL
都会终止 shell 但不会终止其子进程,我不记得有什么好的方法可以做到这一点。我能想到的最好的方法是使用shell=False
,否则当您终止父 shell 进程时,它将留下一个已停用的 shell 进程。
解决方案 6:
这些答案对我都不起作用,所以我保留了有效的代码。在我的情况下,即使使用 终止进程.kill()
并获取.poll()
返回代码后,进程也没有终止。
subprocess.Popen
按照文档说明:
“...为了正确清理,行为良好的应用程序应该终止子进程并完成通信...”
proc = subprocess.Popen(...)
try:
outs, errs = proc.communicate(timeout=15)
except TimeoutExpired:
proc.kill()
outs, errs = proc.communicate()
在我的情况下,我错过了proc.communicate()
调用之后proc.kill()
。这将清除进程的 stdin、stdout...并终止该进程。
解决方案 7:
正如 Sai 所说,shell 是子进程,因此信号被它拦截——我发现最好的方式是使用 shell=False 并使用 shlex 来分割命令行:
if isinstance(command, unicode):
cmd = command.encode('utf8')
args = shlex.split(cmd)
p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
然后 p.kill() 和 p.terminate() 应该按您预期的方式工作。
解决方案 8:
向组内所有进程发送信号
self.proc = Popen(commands,
stdout=PIPE,
stderr=STDOUT,
universal_newlines=True,
preexec_fn=os.setsid)
os.killpg(os.getpgid(self.proc.pid), signal.SIGHUP)
os.killpg(os.getpgid(self.proc.pid), signal.SIGTERM)
解决方案 9:
对于 Python 3.5+,有一个非常简单的方法(实际上在 Python 3.8 上测试过)。
import subprocess, signal, time
p = subprocess.Popen(['cmd'], shell=True)
time.sleep(5) #Wait 5 secs before killing
p.send_signal(signal.CTRL_C_EVENT)
然后,如果您有键盘输入检测或类似的东西,您的代码可能会在某个时候崩溃。在这种情况下,在出现错误的代码/函数行上,只需使用:
try:
FailingCode #here goes the code which is raising KeyboardInterrupt
except KeyboardInterrupt:
pass
这段代码所做的只是向正在运行的进程发送“ CTRL
+ C
”信号,这将导致进程被终止。
解决方案 10:
对我有用的解决方案
if os.name == 'nt': # windows
subprocess.Popen("TASKKILL /F /PID {pid} /T".format(pid=process.pid))
else:
os.kill(process.pid, signal.SIGTERM)
解决方案 11:
完整的解决方案,在超时或特定条件下通过回调函数终止正在运行的进程(包括子树)。适用于 Windows 和 Linux,从 Python 2.7 到 3.12,以及截至撰写本文时 pypy 3.6 到 pypy 3.10,有关更多信息,请参阅https://github.com/netinvent/command_runner
安装pip install command_runner
超时示例:
from command_runner import command_runner
# Kills ping after 2 seconds
exit_code, output = command_runner('ping 127.0.0.1', shell=True, timeout=2)
特定条件的示例:如果当前系统时间秒数大于 5,我们将停止 ping
from time import time
from command_runner import command_runner
def my_condition():
# Arbitrary condition for demo
return True if int(str(int(time()))[-1]) > 5
# Calls my_condition() every second (check_interval) and kills ping if my_condition() returns True
exit_code, output = command_runner('ping 127.0.0.1', shell=True, stop_on=my_condition, check_interval=1)
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件