简体   繁体   English

在python中从管道读取是不可能的

[英]Reading from pipe in python is imposiible

Hello I have the following code in python 2.6: 您好,我在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

The purpose of this code is to sniff the traffic between two processes (A and B) that communicate on port 5559. 此代码的目的是嗅探在端口5559上进行通信的两个进程(A和B)之间的通信。

Now let me describe the different scenarios I am having: 现在让我描述一下我遇到的不同情况:

1) Code above is not running: A and B are communicating and i can see it clearly using logs and the linux command netstat -napl | grep 5559 1)上面的代码未运行:A和B正在通信,我可以使用日志和linux命令netstat -napl | grep 5559清楚地看到它netstat -napl | grep 5559 netstat -napl | grep 5559 shows that the processes are communicating on the desired port. netstat -napl | grep 5559显示进程正在所需的端口上进行通信。

2) Code above is not running and I am sniffing by running tcpflow -c -i any port 5559 directly from shell: I can see the communication on console clearly :-). 2)上面的代码未运行,我通过直接从shell运行tcpflow -c -i any port 5559嗅探:我可以清楚地在控制台上看到通信:-)。

3) Code above is running: Proccesses can't communicate. 3)上面的代码正在运行:过程无法进行通信。 netstat -napl | grep 5559 netstat -napl | grep 5559 prints nothing and logs give out errors!!! netstat -napl | grep 5559打印任何内容,日志会显示错误!!!

4) Code above is running in debug mode: I can't seem to be able to step after the line line = port_sniffer.stdout.readline() 4)上面的代码在调试模式下运行:我似乎无法在line = port_sniffer.stdout.readline()

I tried using an iterator instead of a while loop (not that it should matter but still I am pointing it out). 我尝试使用迭代器而不是while循环(这并不重要,但仍在指出)。 I also tried different values for bufsize (none, 1, and 8). 我还尝试了bufsize的其他值(none,1和8)。

Please help!! 请帮忙!!

So after a quick read through the docs I found these two sentences: 因此,快速浏览文档后,我发现了以下两个句子:

On Unix, if args is a string, the string is interpreted as the name or path of the program to execute 在Unix上,如果args是字符串,则将该字符串解释为要执行的程序的名称或路径

and

The shell argument (which defaults to False) specifies whether to use the shell as the program to execute. shell参数(默认为False)指定是否将shell用作要执行的程序。 If shell is True, it is recommended to pass args as a string rather than as a sequence. 如果shell为True,建议将args作为字符串而不是序列传递。

Based on this, I would recommend recreating your command as a list: 基于此,我建议将您的命令重新创建为列表:

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

The general idea is this (also from the docs): 总体思路是这样的(也来自文档):

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. 如果args是序列,则第一项指定命令字符串,任何其他项都将被视为shell本身的其他参数。 That is to say, Popen does the equivalent of: 也就是说,Popen等效于:

Popen(['/bin/sh', '-c', args[0], args[1], ...])

Additionally , it seems that to read from your process, you should use communicate() . 另外 ,似乎要从您的进程中读取,应该使用communicate() So 所以

while True:
    line = port_sniffer.stdout.readline()

would become 会成为

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

But keep in mind this note from the docs: 但是请记住以下来自文档的注释:

Note The data read is buffered in memory, so do not use this method if the data size is large or unlimited. 注意读取的数据缓存在内存中,因此,如果数据大小很大或没有限制,请不要使用此方法。

If I had to guess, I think the problem that you're having is that you aren't running your program as root. 如果我不得不猜测,我认为您遇到的问题是您没有以root用户身份运行程序。 TCPFlow needs to be run as a privelaged user if you want to be able to sniff other people's traffic (otherwise that'd be a serious security vulnerability). 如果您希望能够嗅探其他人的流量,则必须以特权用户身份运行TCPFlow(否则这将是一个严重的安全漏洞)。 I wrote the following programs and they worked just fine for your scenario 我编写了以下程序,它们在您的情况下工作正常

server.py server.py

#!/usr/bin/python
import socket
s = socket.socket()
host =  socket.gethostname()
port = 12345
s.bind((host,port))
s.listen(5)
while True:
    c, addr = s.accept()
    print 'Connection from', addr
    c.send('Test string 1234')
    c.recv(1024)
    while x != 'q':
        print "Received " + x
        c.send('Blah')
        x = c.recv(1024)
    print "Closing connection"
    c.close()

client.py client.py

#!/usr/bin/python
import socket, sys
from time import sleep
from datetime import datetime
s = socket.socket()
host = socket.gethostname()
port = 12345
s.connect((host,port))
c = sys.stdin.read(1) # Type a char to send to initate the sending loop
while True:
   s.send(str(datetime.now()))
   s.sleep(3)
   msg = s.recv(1024)

flow.py flow.py

#!/usr/bin/python
import subprocess
command = 'tcpflow -c -i any port 12345'
sniffer = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
while True:
   print sniffer.stdout.readline()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM