您好,我在Python2.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)上面的代码是在调试模式下运行的:我似乎无法在line = port_sniffer.stdout.readline()
我尝试使用迭代器而不是while循环(这不重要,但我仍然指出它)。我还尝试了bufsize的不同值(none、1和8)。
请帮忙!!

最佳答案

所以在快速阅读the docs之后,我发现了这两句话:
在Unix上,如果args是一个字符串,则该字符串将被解释为名称或
要执行的程序的路径

shell参数(默认为False)指定是否使用
作为要执行的程序的外壳。如果shell是真的,那么它就是
建议将参数作为字符串而不是序列传递。
基于此,我建议将命令重新创建为列表:

command = ["tcpflow -c", "-i any port 5559"]   #I don't know linux, so double check this line!!

一般的想法是这样的(同样来自文档):
如果args是一个序列,则第一项指定命令字符串,
任何附加项都将被视为
外壳本身。也就是说,Popen的作用相当于:
Popen(['/bin/sh', '-c', args[0], args[1], ...])

此外,要从进程中读取数据,应该使用communicate()。所以
while True:
    line = port_sniffer.stdout.readline()

会变成
while True:
    line = port_sniffer.communicate()[0]

但请记住文档中的注释:
注意,数据读取是在内存中缓冲的,因此如果数据大小很大或不受限制,请不要使用此方法。

08-19 21:45