子进程 PIPE stdout 到两个不同的进程

Subprocess PIPE stdout to two different processes

我正在尝试将 subprocess stdout 重定向到两个不同的进程。 对一个工作正常,但不完全适用于两个不同的进程

代码:

def terminate_processes(*args):
    try:
        for i in reversed(args):
            try:
                i.terminate()
            except:
                pass
    except:
        pass

def main(x='192.168.0.2'):


    # system('sudo nmap -O '+x+'|grep "Running: " > os_detect.txt')
    # system('cat os_detect.txt|cut -d " " -f2 > os.txt')
    # system('cat os_detect.txt|cut -d " " -f3 > os_version.txt')
    
    p1 = subprocess.Popen(['sudo', 'nmap', '-O', str(x)], stdout=subprocess.PIPE)
    
    p2 = subprocess.Popen(['grep', 'Running: '],  stdin=p1.stdout, stdout=subprocess.PIPE)
    
    p3 = subprocess.Popen(['cut', '-d', ' ', '-f2'],  stdin=p2.stdout,
                                                    stdout=subprocess.PIPE, 
                                                    stderr=subprocess.STDOUT,
                                                    universal_newlines=True)
    
    p4 = subprocess.Popen(['cut', '-d', ' ', '-f3'],  stdin=p2.stdout,
                                                    stdout=subprocess.PIPE, 
                                                    stderr=subprocess.STDOUT,
                                                    universal_newlines=True)

    while p3.poll() is None:
        for line in p3.stdout.readlines():
            if line.strip():
                print(line.strip())

    while p4.poll() is None:
        for line in p4.stdout.readlines():
            if line.strip():
                print(line.strip())

    terminate_processes(p1,p2,p3,p4)

正如我所说,理论上应该有效,因为仅使用 p3 而不是 p4 时有效, 但在这种情况下不起作用可能是因为 stdout 被锁定了。

任何指导将不胜感激。

我正在反转终止函数中的 args 数组,导致在杀死父进程之前先杀死子进程。

.read() 通常的工作方式,在我所知道的大多数情况下,为了再次使用它,您必须使用 .seek() 倒回阅读回到原来的地方。

见:

  • Why can't I call read() twice on an open file?

你可以做的是使用 communicate 并手动传入标准输出数据(读取一次,传入两次):

out, err = p2.communicate() # out is None, since you don't 

p2_output = ''.join(list(out))

p3 = Popen([...], stdin=PIPE, ...)
p4 = Popen([...], stdin=PIPE, ...)

stdout_data3, err = p3.communicate(input=p2_output)
stdout_data4, err = p4.communicate(input=p2_output)

另请注意,与您目前的方式相比,这可能会改变需要进行轮询的方式。

相关:

  • How do I write to a Python subprocess' stdin?
  • How to read output from subprocess Popen correctly?