原创 推荐
1066897515 关注 2 人评论 407 人阅读 2019-10-09 15:03:38
因公司服务器上部署应用较多, 在有大并发访问, 业务逻辑有问题的情况下反复互相调用或者有异常流量访问的时候, 需要对业务应用进行故障定位, 所以利用 python 调用 iftop 命令来获取应用进程流量, 结合 zabbix, 可帮助定位分析问题., 以下是脚本内容, 大概思路是:
利用 iftop 命令 iftop -t -P -N -n -s 2 来获取流量信息
对获取的流量信息进行处理, 单位换算, 同一个应用程序的所有链接流量进行合计(因为一个应用会有很多链接, 每一个链接都有流量, 全部相加即可得出这个应用的总流量)
- #!/usr/bin/python
- #coding=utf-8
- # 针对业务监听的端口流量进行统计, 忽略对随机端口流量统计
- # 若针对突然流量增大, 找到其进程进行告警, 可以不做统计, 获取到流量进行判断, 若大于多少阀值, 则输出
- 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 参数:-t 使用不带 ncurses 的文本界面,-P 显示主机以及端口信息,-N 只显示连接端口号, 不显示端口对应的服务名称,-n 将输出的主机信息都通过 IP 显示, 不进行 DNS 解析,-s num num 秒后打印一次文本输出然后退出
- mes = os.popen("iftop -t -P -N -n -s 2 2>/dev/null |grep -A 1 -E'^ [0-9]'").read()
- # 以换行符进行分割
- iftop_list = mes.split("\n")
- count = len(iftop_list)
- # 定义字典 存放主机信息和进出流量
- flow_dict = {
- }
- # 定义列表, 存放主机信息
- host_ips = []
- # 把主机加入数组, 新的主机查询是否在列表里面, 没有的话, 把主机信息加入 host_ips, 并新组装一个字典值加入 flow_dict 字典, 如果 host_ips 存在主机信息, 则把字典值取出来, 重新计算增加流量数值, 再加入字典 flow_dict
- # 这里的 count/2 是 iftop 获取到的数据, 是进出流量为一组, 则有 count/2 个流量连接, 可执行 os.popen 里面的 iftop 命令即可明白
- for i in range(count/2):
- flow_msg = ""
- # 获取发送的 ip 地址(本地 ip 地址), 端口(本地端口), 发送的流量, 以换行符分割后, 数据偶数位为本地发送流量信息
- location_li_s = iftop_list[i*2]
- send_flow_lists = location_li_s.split(" ")
- # 去空元素
- 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
- # 获取接收的流量
- 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)
- # 去掉本地 Linux 大于 10000 的随机端口, 因为公司业务应用无大于 10000, 也可把这里去掉
- port = host_ip.split(":")[1]
- if int(port) < 10000:
- # 主机信息若不存在列表则加入 host_ips, 若存在, 则字典取值, 对进出流量进行相加
- 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(":")
- # 获取字典里的发送接收流量
- flow_dict_msg_send = float(flow_dict_msg_li[0])
- flow_dict_msg_rec = float(flow_dict_msg_li[1])
- # 字典里面的发送接收流量和获取到的新流量相加
- flow_add_send = flow_dict_msg_send + send_flow_float
- flow_add_rec = flow_dict_msg_rec + rec_flow_float
- # 把新得出的结果, 更新到字典
- 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]为发送流量, flow_li[1]为接收流量, 单位是 Kb
- print key + "|" + flow_li[0] + "|" + flow_li[1]
- get_flow()
来源: http://blog.51cto.com/zdhyw/2440716