你好,我在 python 2.6 中有以下代码:
command = "tcpflow -c -i any port 5559"
port_sniffer = subprocess.Popen(command, stdout=subprocess.PIPE, bufsize=1, shell=True)
while True:
line = port_sniffer.stdout.readline()
#do some stuff with line
此代码的目的是嗅探在端口 5559 上通信的两个进程(A 和 B)之间的流量。
现在让我描述一下我遇到的不同场景:
1) 上面的代码没有运行: A 和 B 正在通信,我可以使用日志和 linux 命令 netstat -napl | 清楚地看到它grep 5559
显示进程正在所需端口上进行通信。
2) 上面的代码没有运行,我通过直接从 shell 运行 tcpflow -c -i any port 5559
来嗅探: 我可以清楚地看到控制台上的通信:-)。
3) 上面的代码正在运行:进程无法通信。 netstat -napl | grep 5559
什么都不打印,日志给出错误!!!
4) 上面的代码在 Debug模式下运行:我似乎无法在 line = port_sniffer.stdout.readline()
我尝试使用迭代器而不是 while 循环(这并不重要,但我仍然指出了这一点)。我还尝试了不同的 bufsize 值(无、1 和 8)。
请帮忙!!
请您参考如下方法:
所以在快速阅读 the docs 之后我找到了这两句话:
On Unix, if args is a string, the string is interpreted as the name or path of the program to execute
和
The shell argument (which defaults to False) specifies whether to use the shell as the program to execute. If shell is True, it is recommended to pass args as a string rather than as a sequence.
基于此,我建议将您的命令重新创建为列表:
command = ["tcpflow -c", "-i any port 5559"] #I don't know linux, so double check this line!!
总体思路是这样的(也来自文档):
If args is a sequence, the first item specifies the command string, and any additional items will be treated as additional arguments to the shell itself. That is to say, Popen does the equivalent of:
Popen(['/bin/sh', '-c', args[0], args[1], ...])
此外,似乎要从您的进程中读取数据,您应该使用communicate()
。所以
while True:
line = port_sniffer.stdout.readline()
会变成
while True:
line = port_sniffer.communicate()[0]
但请记住文档中的这条注释:
Note The data read is buffered in memory, so do not use this method if the data size is large or unlimited.