2014-01-20 4 views
0

Привет У меня есть следующий код в Python 2.6:Чтение из трубы в питона imposiible

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 .

Теперь позвольте мне описать различные сценарии, я имею:

1) Код выше не работает: а и в общении и я могу видеть это ясно с помощью журналов и команды Линукс netstat -napl | grep 5559 показывает, что пр ocesses общаются на нужном порту.

2) Код выше не работает, и я нюхаю, запустив tcpflow -c -i any port 5559 прямо из оболочки: Я вижу сообщение на консоли ясно :-).

3) Выполняется код выше: Пропуск не может связываться. netstat -napl | grep 5559 ничего не печатает, а журналы выдают ошибки !!!

4) Код выше работает в режиме отладки: Я не могу быть в состоянии уйти после того, как линии line = port_sniffer.stdout.readline()

Я попытался с помощью итератора вместо цикла While (не то, что это имеет значение, но все-таки Я указываю это). Я также пробовал разные значения для bufsize (нет, 1 и 8).

Пожалуйста, помогите!

+0

tcpflow не стандартная программа. Можете ли вы рассказать о том, что делает 'tcpflow -c -i любой порт 5559'? Оставляет ли он данные только в файл или выводит информацию в stdout/stderr? – FuriousGeorge

+0

О, и FWIW http://stackoverflow.com/questions/3172470/actual-meaning-of-shell-true-in-subprocess – FuriousGeorge

+0

tcpflow захватывает tcp-пакеты и записывает их тело сообщения (без накладных расходов tcp) в файлы или консоль. Флаг -c заставляет его записывать свой вывод на консоль. Я предпочел бы использовать shell = True, потому что я не знаю, какая другая среда может запустить эту программу. – whomaniac

ответ

1

Таким образом, после быстрого чтения через the docs Я нашел эти два предложения:

На Unix, если арг это строка, строка интерпретируется как имя или путь к программе для выполнения

и

аргумент оболочки (который по умолчанию False) указывает, следует ли использовать корпусу программа для выполнения. Если shell True, то рекомендуется передавать args как строку, а не как последовательность.

Исходя из этого, я рекомендовал бы воссоздать вашу команду в списке:

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

Основная идея заключается в следующем (также из документации):

Если арг представляет собой последовательность , первый элемент указывает командную строку, , и любые дополнительные элементы будут рассматриваться как дополнительные аргументы для самой оболочки. То есть, Popen делает эквивалент:

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

Кроме, это кажется, что читать с вашего процесса, вы должны использовать communicate().Так

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

станет

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

Но имейте в виду, это примечание из документации:

Примечание Считанные данные забуференного в памяти, поэтому не используйте этот метод если размер данных является большим или неограниченным.

+0

Спасибо за ваш вклад, но я не думаю, что это решает проблему. Использование списка или строки делает то же самое. Что касается общения, я не пробовал, потому что знаю, что он блокирует. То, что я хочу сделать, это прочитать из stdout tcpflow во время его работы. Я не хочу, чтобы это закончилось! – whomaniac

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() 
Смежные вопросы