与孩子的孩子互动

时间:2019-02-28 01:51:17

标签: python linux subprocess file-descriptor


我需要直接与通过stdin生成的进程的stdoutsubprocess进行交互。我可以做到:

proc = subprocess.Popen("/bin/bash", stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
proc.stdin.write(b"whoami\n")
print(proc.stdout.readline())

但是,一旦进程分叉,我就无法与其进行交互。我有这个测试程序:

// child.c
#include <unistd.h>
int main() {
    execve("/bin/bash", NULL, NULL);
}
我编译时使用的

gcc -o child child.c

,当我在child调用中使用/bin/bash而不是Popen尝试上述python代码时,出现broken pipe错误。

我尝试过的:
由于默认情况下,由python创建的文件描述符是不可继承的,因此我尝试更改它:

inr, inw = os.pipe()
outr, outw = os.pipe()
os.set_inheritable(inr, True)
os.set_inheritable(inw, True)
os.set_inheritable(outr, True)
os.set_inheritable(outw, True)

proc = subprocess.Popen("./child", stdin=inr, stdout=outw, stderr=outw)
proc.stdin.write(b"whoami\n")
print(proc.stdout.readline())

os.close(inr)
os.close(inw)
os.close(outr)
os.close(outw)

但是我仍然遇到相同的错误。我认为这应该是一件容易的事,而且我可能会缺少一些东西。感谢您的帮助。

[EDIT]在编辑帖子之前,我使用test代替child作为测试c可执行文件的名称。我了解到它确实是我的PATH中位于/usr/bin/test上的程序。
将可执行文件名称更改为child成功解决了我的问题。经过数小时的尝试和错误,我知道答案将变得如此简单...
非常感谢Barmar指出这一点!

1 个答案:

答案 0 :(得分:1)

调用test时,您调用的是/bin/test,而不是程序。

要么重命名C程序,使其不与标准命令冲突,要么使用路径名访问它,从而不会搜索$PATH

proc = subprocess.Popen("./test", stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)