python script calls iftop to count business application traffic

Posted by scottbarry on Thu, 10 Oct 2019 02:41:52 +0200

Because there are many applications deployed on the company's servers, when there are large concurrent access, business logic problems and repeated calls to each other or abnormal traffic access, it is necessary to locate the fault of business applications. Therefore, using python to call iftop command to obtain the application process traffic, combined with zabbix, can help locate and analyze the problem. The following is the content of the script, the general idea is:

  1. Using iftop command iftop-t-P-N-n-s 2 to obtain traffic information
  2. Processing the acquired traffic information, unit conversion, and summing up all the link traffic of the same application (because there are many links in an application, each link has traffic, the total traffic of the application can be obtained by adding all the links)
#!/usr/bin/python
#coding=utf-8
#Statistical analysis of port traffic monitored by traffic, ignoring random port traffic statistics
#If the alarm is given to find the process of sudden flow increase, the flow can be judged without statistics. If the value is greater than the threshold, the output will be obtained.
import os
def change_unit(unit):
    if "Mb" in unit:
        flow = float(unit.strip("Mb")) * 1024
        return flow
    elif "Kb" in unit:
        flow = float(unit.strip("Kb"))
        return flow
    elif "b" in unit:
        flow = float(unit.strip("b")) / 1024
        return flow

def get_flow():
    #iftop parameter: - t uses a text interface without ncurses, - P displays host and port information, - n only displays the connection port number, does not display the service name corresponding to the port, - n displays the output host information through IP, does not perform DNS parsing, - s num num prints text output once in seconds and then exits.
    mes = os.popen("iftop -t -P -N -n -s 2 2>/dev/null |grep -A 1 -E '^   [0-9]'").read()
    #Segmentation with line breaks
    iftop_list = mes.split("\n")
    count = len(iftop_list)
    #Define dictionaries to store host information and incoming and outgoing traffic
    flow_dict = {}
    #Define lists to store host information
    host_ips = []

# Add the host to the array, the new host query whether in the list, if not, add the host information to the host_ips, and assemble a new dictionary value to join the flow_dict dictionary. If host_ips has host information, then take out the dictionary value, recalculate the increase traffic value, and add the dictionary flow_dict.
    #Here, count/2 is the data obtained by iftop. It is a group of incoming and outgoing traffic. There are count/2 traffic connections. It can be understood by executing the iftop command in os.popen.
    for i in range(count/2):
        flow_msg = ""
        #Get the ip address (local ip address), port (local port), and traffic sent. After line breaking, data even bits send traffic information locally.
        location_li_s = iftop_list[i*2]
        send_flow_lists = location_li_s.split(" ")
        #Empty element
        while '' in send_flow_lists:
            send_flow_lists.remove('')
        host_ip = send_flow_lists[1]
        send_flow = send_flow_lists[3]
        send_flow_float = change_unit(send_flow)
        #print send_flow_lists
        #Acquire received traffic
        location_li_r = iftop_list[i*2+1]
        rec_flow_lists = location_li_r.split(" ")
            while '' in rec_flow_lists:
                    rec_flow_lists.remove('')
            rec_flow = rec_flow_lists[3]
        rec_flow_float = change_unit(rec_flow)  
        #Remove random ports with local linux greater than 10,000, because there are no more than 10,000 business applications in the company, you can also remove them here.
        port = host_ip.split(":")[1]
        if int(port) < 10000:
        #If there is no list of host information, host_ips is added. If there is a list of host information, the dictionary takes the value and adds the incoming and outgoing traffic.
            if host_ip not in host_ips:
                    host_ips.append(host_ip)
                    flow_msg = str(float('%2.f' % send_flow_float)) + ":" + str(float('%.2f' % rec_flow_float))
                    flow_dict[host_ip]=flow_msg
                else:
                    flow_dict_msg = flow_dict[host_ip]
                    flow_dict_msg_li = flow_dict_msg.split(":")
                    #Get the sending and receiving traffic in the dictionary
                    flow_dict_msg_send = float(flow_dict_msg_li[0])
                    flow_dict_msg_rec = float(flow_dict_msg_li[1])
                    #The sum of the received and sent traffic in the dictionary and the acquired new traffic
                    flow_add_send = flow_dict_msg_send + send_flow_float
                    flow_add_rec = flow_dict_msg_rec + rec_flow_float
                    #Update the new results to the dictionary
                    flow_msg = str(float('%.2f' % flow_add_send)) + ":" + str(float('%.2f' % flow_add_rec))
                    flow_dict[host_ip]=flow_msg
    for key in flow_dict:
        flow_li = flow_dict[key].split(":")
        #flow_li[0] is the sending traffic and flow_li[1] is the receiving traffic.
        print key + "|" + flow_li[0]  + "|" +  flow_li[1]

get_flow()

Topics: Linux Python Zabbix DNS