2017-04-24 72 views
0

我得从我的老板工作代码,记录所有的广播流量,并对其进行分析。现在,我必须在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) 
+0

如果底层程序不刷新其输出,还有这是相当多的代码有什么可以做... –

+0

......你只对tshark输出感兴趣? – tdelaney

+2

来自[D.2。 tshark:基于终端的Wireshark](https://www.wireshark.org/docs/wsug_html_chunked/AppToolstshark.html)_ -l在每个packet_之后刷新标准输出...对于那些难于阅读字体的人来说,这是一个“ell” 。 – tdelaney

回答

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\"" 
+0

@eryksun嗯,我想我可以这样做,但这种perfectely回答的作品。 :d –

+0

@M.Kälin,我是在回应这个答案的第一句话。我很高兴提议的解决方案能够完美地为您服务。 – eryksun

+0

@eryksun好吧,我将修改。我知道这是一个禁止在Windows上。因为它是社区维基,我被允许剥离其他人的工作:) –