问题描述
我正在使用os库在python中制作外壳程序,并且希望实现多个管道功能,但是由于无法确定如何处理STDOUT和孩子以及父母,我陷入了困境。
我想我必须继续将结果写入stdout并在有更多管道的情况下将其复制。
因此,如果我有此命令,我应该只获得找到var的行:
ls -l / | grep v | grep var
然后,我使外壳将命令分为字符串列表:
command = [['ls','-l','/'],['grep','root'],'var']]
然后,我需要在新的孩子中派生并复制前两个的输出,并将输出传递到最后一个。
我对如何使用1个以上的管道执行此操作感到非常困惑,甚至对如何动态执行此操作感到困惑。
我现在坐在那里,尝试以不同的方式向程序中静态添加第二个管道,但是我对如何动态地向程序中添加 n 个管道有一些想法通过使用迭代或递归。
from os import (
execvp,wait,fork,pipe,dup2,_exit,close,)
STDIN = 0
STDOUT = 1
CHILD = 0
def command(cmd):
try:
execvp(cmd[0].strip(),cmd)
except OSError as e:
print(e)
def piping(cmd):
reading,writing = pipe()
pid = fork()
if pid > CHILD:
wait()
close(writing)
dup2(reading,STDIN)
command(cmd[1])
elif pid == CHILD:
close(reading)
dup2(writing,STDOUT)
command(cmd[0])
_exit(0)
def main():
pid = fork()
if pid > CHILD:
wait()
if pid == CHILD:
piping([['ls','-al','v'],'var']])
_exit(0)
main()
因此,要想使用3个管道,我想我可以做这样的事情。但这不起作用。
我只是更改了pipeline()函数以在孩子内部获得一个额外的fork,并使用dup2方法交换新旧管道中通道的输入/输出。
def piping(cmd):
print(cmd)
r1,w1 = pipe()
pid = fork()
if pid > CHILD:
wait()
close(w1)
dup2(r1,STDIN)
command(cmd[2])
elif pid == CHILD:
r2,w2 = pipe()
pid2 = fork()
if pid2 > CHILD:
wait()
close(w2)
close(r1)
dup2(w1,r2)
command(cmd[1])
elif pid2 == CHILD:
close(r2)
dup2(w2,STDOUT)
command(cmd[0])
_exit(0)
请帮助我,我真的很想学习如何做!谢谢:-)
解决方法
我知道了!
我只需要创建一个函数 child()即可负责创建新管道和新派生。然后仅写入父级的那个通道。
所以我将 piping()函数更改为此。
def piping(cmd):
reading,writing = pipe()
pid = fork()
if pid > CHILD:
wait()
close(writing)
dup2(reading,STDIN)
command(cmd[len(cmd)-1])
elif pid == CHILD:
child(cmd[:-1],reading,writing)
然后我创建了 child()函数:
def child(cmd,r1,w1):
r2,w2 = pipe()
pid2 = fork()
if pid2 > CHILD:
wait()
close(w2)
close(r1)
dup2(r2,STDIN)
dup2(w1,STDOUT)
command(cmd[len(cmd)-1])
elif pid2 == CHILD:
if len(cmd) > 2:
child(cmd[:-1],r2,w2)
else:
close(r2)
dup2(w2,STDOUT)
command(cmd[0])
_exit(0)
然后我就可以将无数个管道传递给shell并获得结果! :D