如何结束我的Python可执行文件用sudo启动的进程?

1 投票
2 回答
58 浏览
提问于 2025-04-12 13:56

我正在用这段Python代码来运行一个C++程序:

import os
import subprocess
import signal
import time

def trench():
    return subprocess.Popen(
        ['sudo', './Trench.out'],
        stdout=subprocess.DEVNULL,
        stderr=subprocess.STDOUT,
    )

trench_display = trench()

time.sleep(5)

os.kill(trench_display.pid, signal.SIGINT)

我也试过这个方法,但似乎没有什么变化:

trench_display.send_signal(signal.SIGINT)

问题是,当Python代码运行结束后,C++程序还在继续运行。如果我输入任何命令并按下回车,终端就会出现问题,程序似乎无法正常退出。

但是,如果我直接在终端里运行这个程序,然后使用 kill -2 PID 或者 Ctrl + C,它就能正常退出。所以,我觉得问题出在Python的子进程上。

我知道这是Python子进程的一个小毛病,但我想知道有没有办法解决这个问题,而不需要修改C++的源代码?

2 个回答

1

一个很简单明了的答案就是:直接用 subprocess.popen 来运行 sudo kill ...,就像你最开始启动这个进程时那样。你的程序直接发出的系统调用是没有权限去结束那些权限更高的子进程的。

0

在现实生活中,你可以通过更新权限来解决这个问题,这样就不需要用到 sudo 来执行 i2c 操作(这确实是解决这个问题的最佳方法!)。不过,这里有一个替代的方法,适合这个问题的范围:

import os
import subprocess
import signal
import time

def trench():
    p1 = subprocess.Popen(
        ['sudo', './Trench.out'],
        stdout=subprocess.DEVNULL,
        stderr=subprocess.PIPE,
    )
    p2 = subprocess.Popen(['cat'], stdin=p1.stdout)
    p1.stdout.close()
    return p2

trench_display = trench()
time.sleep(5)
trench_display.send_signal(signal.SIGTERM)

注意,trench_display 不再指代 sudo ./Trench.out,而是指代 cat。所以当你结束这个进程时,下次 Trench.out 尝试写入它的错误输出时,会出现 EPIPE 错误和 SIGPIPE 信号;除非它特别设置去忽略这两者,否则这会导致 Trench 即使在更高权限的用户下也会退出。

当然,你也可以写 Python 代码来将 p1.stdout 的内容复制到 Python 项目的标准输出中——使用 cat 只是为了让这个回答简短一点。:)

撰写回答