您需要确保第三个进程的标准输出和标准错误定向到除发出该进程的管道之外的其他位置。af_audit_run.py
正在读取输出。
现有代码的问题在于使用stdout=None, stderr=None
,您正在请求default操作(就好像您根本没有使用过这些关键字一样)。这是写入与父进程相同的输出流,在本例中request_audit.py
,使用子进程分叉时继承的文件描述符。这意味着顶层af_audit_run.py
将等待输出,因为在第三个进程完成之前它不会在该输出流上看到文件结尾。
这可以在输出中看到lsof
- 在下面的例子中,第三个进程是命令/bin/sleep 600
(参见最后的测试代码)。
这是其中的一部分lsof
第三个过程的输出:
sleep 3057 myuser 0u CHR 136,20 0t0 23 /dev/pts/20
sleep 3057 myuser 1w FIFO 0,13 0t0 9441062 pipe
sleep 3057 myuser 2w FIFO 0,13 0t0 9441063 pipe
这是其中的一部分lsof
顶层的输出af_audit_run.py
:
python3 3053 myuser 0u CHR 136,20 0t0 23 /dev/pts/20
python3 3053 myuser 1u CHR 136,20 0t0 23 /dev/pts/20
python3 3053 myuser 2u CHR 136,20 0t0 23 /dev/pts/20
python3 3053 myuser 3r FIFO 0,13 0t0 9441062 pipe
python3 3053 myuser 5r FIFO 0,13 0t0 9441063 pipe
如您所见,sleep
本例中的进程 (pid 3057) 的 stdout (fd 1) 和 stderr (fd 2) 流连接到顶级进程 (pid 3053) 正在读取的管道的写入端 - 请注意倒数第二列——即使它不是该进程的直接父进程。
您正在指定close_fds=True
,但这就是有记录的 https://docs.python.org/3/library/subprocess.html如下:
"If 关闭_fds为 true,所有文件描述符除了 0、1 和 2将在子进程执行之前关闭。”(强调我的)
因此,它对 stdin、stdout 或 stderr 流没有任何影响,尽管有任何影响other打开的文件描述符将在子进程中关闭。
如果代替stdout=None, stderr=None
你用stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
,那么这将显式地将这些流定向到空设备(/dev/null
在 Linux 上),然后af_audit_run.py
不必等待。
一些输出来自lsof
在这种情况下:
sleep 3318 myuser 0u CHR 136,20 0t0 23 /dev/pts/20
sleep 3318 myuser 1u CHR 1,3 0t0 6 /dev/null
sleep 3318 myuser 2u CHR 1,3 0t0 6 /dev/null
也可以使用stdin=subprocess.DEVNULL
这样,如果进程尝试读取,它将看到文件结尾。在这个例子中我没有这样做,它的输入仍然连接到终端设备,尽管这并不影响是否af_audit_run.py
等待它。
测试代码
af_audit_run.py
import subprocess
cmd = "python3 request_audit.py"
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
result, error = p.communicate()
print(result.decode('utf-8'))
print(error.decode('utf-8'))
request_audit.py
import subprocess
cmd = "/bin/sleep 600"
subprocess.Popen(cmd, shell=True,
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
print(5)