2017-04-24 52 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上。因爲它是社區維基,我被允許剝離其他人的工作:) –