没有终止子进程的标准输出

时间:2019-04-30 12:43:51

标签: python subprocess stdout scapy kill

我有一项家庭作业,目的是捕获用户和AP之间通过Scapy进行的4way握手。我试图使用“ aircrack-ng capture.pcap”来检查我使用scapy创建的捕获文件中的有效握手

我使用Popen启动程序。该程序等待用户输入,所以我必须杀死它。当我在杀死它后尝试获取stdout时,输出为空。

我已经尝试过stdout.read(),我已经尝试过通信,我已经尝试过阅读stderr,并且我已经尝试过带壳和不带壳

check=Popen("aircrack-ng capture.pcap",shell=True,stdin=PIPE,stdout=PIPE,stderr=PIPE)
check.kill()    
print(check.stdout.read())

2 个答案:

答案 0 :(得分:1)

虽然您不应该这样做(尝试依赖硬编码的延迟本质上是容易出现竞争条件的原因),但问题是由kill()仍在启动时交付sh引起的可以通过sleep微小的“解决”(不可靠,但足以演示)问题来证明,该问题足够长的时间让shell启动并运行echo

import time
from subprocess import Popen, PIPE

check=Popen("echo hello && sleep 1000", shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)
time.sleep(0.01) # BAD PRACTICE: Race-condition-prone, use one of the below instead.
check.kill()    
print(check.stdout.read())

也就是说,一种更好的实践方法是关闭stdin描述符,以便读取立即返回0字节结果。在较新版本的Python(现代3.x)上,您可以使用DEVNULL

import time
from subprocess import Popen, PIPE, DEVNULL

check=Popen("echo hello && read input && sleep 1000", 
            shell=True, stdin=DEVNULL, stdout=PIPE, stderr=PIPE)
print(check.stdout.read())

...或者使用Python 2.x,可以通过将空字符串传递到communicate(),从而close()立即使用stdin管道来实现类似的效果:

import time
from subprocess import Popen, PIPE

check=Popen("echo hello && read input && sleep 1000", 
            shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)
print(check.communicate('')[0])

答案 1 :(得分:0)

从不,并且我的意思是,从不终止进程是正常操作的一部分。不能保证在终止进程时进程进行了多长时间,因此在这种情况下,您将无法期望得到任何特定的结果。

  • 要明确不向输入传递任何子流程,以防止在尝试读取stdin时挂起:

  • 使用<process>.communicate()或使用subprocess.check_output()而非Popen可靠地读取输出

    • 通常情况下,由于I / O缓冲,不能保证进程在任何特定时刻输出任何数据。因此,您需要在过程完成后读取输出流,以确保您已掌握所有内容。
    • 同时,如果进程可以产生足够的输出以填充I / O缓冲区 1 ,则需要同时读取流。否则,它将挂起,等待您读取缓冲的数据。如果stdoutstderr均为PIPE,则需要同时读取它们 ,即在不同的线程中。
      • communicate()check_output(在后台使用前者)是通过在两个单独的线程中读取stdoutstderr来实现的。
  • 在常用情况下,便捷功能优于Popen (在您的情况下为check_output),因为它们为您解决了上述所有警告


1 管道已完全缓冲,a typical buffer size is 64KB