簡體   English   中英

在python中從管道讀取是不可能的

[英]Reading from pipe in python is imposiible

您好,我在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清楚地看到它netstat -napl | grep 5559 netstat -napl | grep 5559顯示進程正在所需的端口上進行通信。

2)上面的代碼未運行,我通過直接從shell運行tcpflow -c -i any port 5559嗅探:我可以清楚地在控制台上看到通信:-)。

3)上面的代碼正在運行:過程無法進行通信。 netstat -napl | grep 5559 netstat -napl | grep 5559打印任何內容,日志會顯示錯誤!!!

4)上面的代碼在調試模式下運行:我似乎無法在line = port_sniffer.stdout.readline()

我嘗試使用迭代器而不是while循環(這並不重要,但仍在指出)。 我還嘗試了bufsize的其他值(none,1和8)。

請幫忙!!

因此,快速瀏覽文檔后,我發現了以下兩個句子:

在Unix上,如果args是字符串,則將該字符串解釋為要執行的程序的名稱或路徑

shell參數(默認為False)指定是否將shell用作要執行的程序。 如果shell為True,建議將args作為字符串而不是序列傳遞。

基於此,我建議將您的命令重新創建為列表:

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

總體思路是這樣的(也來自文檔):

如果args是序列,則第一項指定命令字符串,任何其他項都將被視為shell本身的其他參數。 也就是說,Popen等效於:

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

另外 ,似乎要從您的進程中讀取,應該使用communicate() 所以

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

會成為

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

但是請記住以下來自文檔的注釋:

注意讀取的數據緩存在內存中,因此,如果數據大小很大或沒有限制,請不要使用此方法。

如果我不得不猜測,我認為您遇到的問題是您沒有以root用戶身份運行程序。 如果您希望能夠嗅探其他人的流量,則必須以特權用戶身份運行TCPFlow(否則這將是一個嚴重的安全漏洞)。 我編寫了以下程序,它們在您的情況下工作正常

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

#!/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

#!/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