用子进程缓冲代码

时间:2017-04-24 14:40:56

标签: python subprocess

我找到了老板的工作,记录所有广播流量并进行分析。现在,我必须在python脚本中执行此操作。到目前为止,我已经编写了脚本,以便读出流量并使用它。然后,我得到了一个输出。这个输出困扰我,因为它有一些缓冲/延迟。现在,我无法找到原因。有人可以帮我吗?

# !/usr/bin/python3.5
import subprocess
import atexit
from datetime import datetime
import signal
import sys
import os


def exit_handler():
    print "\nSkript wurde manuell beendet..."


class Broadcasting_Host:
    def __init__(self, mac="", ips=[]):
        self.mac = mac
        self.broadcast = {}
        print("Broadcasting Host found at: %s" % (mac))

    def broadcasting(self, srcport=0, dstport=0, protokoll="", zeit="", ip="", layer_4_type=""):
        broadcast_key = "%s_%s_%s" % (srcport, dstport, protokoll)
        if ip:
            if ip not in self.broadcast.keys():
                print("User_MAC: %s, has another IP" % (self.mac))
                self.broadcast[ip] = dict()
            # falls dieser broadcast neu ist hinzufuegen
            if broadcast_key not in self.broadcast[ip].keys():
                self.broadcast[ip][broadcast_key] = list()
                print("New broadcast Type detected, for MAC: %s, KEY: %s" % (self.mac, broadcast_key))
        else:
            if "No_IP" not in self.broadcast.keys():
                self.broadcast["No_IP"] = list()
            # broadcast zeit hinzufuegen
        if broadcast_key == "0_0_ARP":
            self.broadcast["No_IP"].append(zeit)
            #print("User: %s, is searching for somebody. KEY: %s" % (self.mac, broadcast_key))
        else:
            self.broadcast[ip][broadcast_key].append(zeit)

        self.drawback

    def drawback(self):
        """gibt die aktuellen broadcast fuer diese object aus"""
        if self.broadcast["ARP"] >= 5:
            print(self.broadcast)
            return self.broadcast

    def cleanup(self):
        pass

    def check_if_correct(self):
        pass


def define_ports(tcp_srcport="", tcp_dstport="", udp_srcport="", udp_dstport=""):
    if tcp_srcport:
        srcport = int(tcp_srcport)
        dstport = int(tcp_dstport)
        layer_type = "TCP"
    elif udp_srcport:
        srcport = int(udp_srcport)
        dstport = int(udp_dstport)
        layer_type = "UDP"
    else:
        srcport, dstport, layer_type = [0, 0, "ARP"]
    return srcport, dstport, layer_type


def split_line(define_ports, line):
    zeit, protokoll, info, mac_source, ip_source, mac_ziel, ip_ziel, tcp_srcport, tcp_dstport, udp_srcport, udp_dstport = line.replace("\n", "").split("\t")
    ms = zeit.split('.')[1].split(" ")[0]
    zeit = datetime.strptime(zeit.replace(ms, ms[:6]), "%b  %d, %Y %H:%M:%S.%f %Z")
    srcport, dstport, layer_4_type = define_ports(tcp_srcport=tcp_srcport, tcp_dstport=tcp_dstport, udp_srcport=udp_srcport, udp_dstport=udp_dstport)
    return zeit, protokoll, info, mac_source, ip_source, mac_ziel, ip_ziel, srcport, dstport, layer_4_type


if __name__ == '__main__':
    # Dies ist eine Funktion die das Traceback beim druecken von CTRL + C unterdrueckt.
    signal.signal(signal.SIGINT, lambda x, y: sys.exit(0))
    # In diesem Programm, benutze ich diese Funktion um beim druecken von CTRL + C noch eine Textausgabe zu bekommen.
    atexit.register(exit_handler)
    # Der Command welcher in einem Subprocess ausgefuehrt wird.
    cmd = "tshark -T fields -e frame.time -e _ws.col.Protocol -e _ws.col.Info -e eth.src -e ip.src -e eth.dst -e ip.dst -e tcp.srcport -e tcp.dstport -e udp.srcport -e udp.dstport -Y \"eth.addr == FF:FF:FF:FF:FF:FF\""
    # Subprocces mit integriertem command
    p = subprocess.Popen(cmd, shell=True, bufsize=0, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    stdout = []
    seltsame_hosts = {}
    while True:
        line = p.stdout.readline()
        #
        #
        if not line:
            # no entries
            continue
        #
        if "Capturing" in line:
            # unnecessary line
            continue
        #
        zeit, protokoll, info, mac_source, ip_source, mac_ziel, ip_ziel, srcport, dstport, layer_4_type = split_line(define_ports, line)
        #
        if mac_source not in seltsame_hosts:
            ips = [ip_source]
            seltsame_hosts[mac_source] = Broadcasting_Host(mac=mac_source, ips=ips)
        #
        seltsame_hosts[mac_source].broadcasting(srcport=srcport, dstport=dstport, protokoll=protokoll, zeit=zeit, ip=ip_source, layer_4_type=layer_4_type)

1 个答案:

答案 0 :(得分:1)

在Linux上,您可以尝试通过stdbuf运行命令来覆盖输出到管道的默认完全缓冲,而不是使用行缓冲或不缓冲。这通常有效,除非程序在启动时手动设置缓冲

在Windows上,如果底层进程没有刷新其输出,那么除了平滑的逐行打印输出之外,您无需执行任何操作,只需等待文本块显示。

但在这种情况下,作为tdelaney pointed out,有一个独立于平台的解决方案:在每一行刷新输出的选项。因此,将-l添加到您的命令中,您将获得常规/更顺畅的输出

cmd = "tshark -l -T fields -e frame.time -e _ws.col.Protocol -e _ws.col.Info -e eth.src -e ip.src -e eth.dst -e ip.dst -e tcp.srcport -e tcp.dstport -e udp.srcport -e udp.dstport -Y \"eth.addr == FF:FF:FF:FF:FF:FF\""