最近网络运维的同事有个小需求,需要我这个弱弱的实习生写个脚本
脚本的功能呢,就是在华为的防火墙上抓取会话数,然后写到prom里被普罗收集到,再到grafana上做展示
我就琢磨着,咱就直接使用python模拟ssh连接登录到防火墙上抓数据下来吧
由于需要获取多个方向的会话数记录,要执行多个命令,所以咱就在这边使用invoke_shell(),完全模拟ssh的交互过程
# 登录和启用shell
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('ip_addr', username='username', password='passwd')
shell = ssh.invoke_shell()
但是文本返回的是这个样子的该怎么办啊?
咱就是想了一个小办法,把命令返回的文本进行了个小处理,整体就是使用正则表达式进行匹配,把78个-开头和78个-结尾的文本提取出来,并且返回,如果遇到了"Start a new statistics?[Y/N]:",则模拟敲入Y并且回车。
因为统计会话数需要时间,所以在发送命令后都要sleep个10秒钟
def send_command(shell, command):
shell.send(command + '\n')
time.sleep(10)
output = shell.recv(4096).decode()
if "Start a new statistics?[Y/N]:" in output:
shell.send('Y\n')
time.sleep(10)
output = shell.recv(4096).decode()
pattern = r'[-]{78}(.*?)[-]{78}'
matches = re.findall(pattern, output, re.DOTALL)
return matches[0]
再然后咱就是封装了一个小函数,将命令返回的数据进行每行的处理,如果判断是有效数据,则把这条记录拼接为一条metrics,并存到list中
def format_output(output, type):
ans = []
for line in output.split("\n"):
items = line.split()
if len(items) == 0:
continue
if not str.isdigit(items[0]):
continue
ans.append(f'firewall_session_topn{{ip="{items[1]}",type="{type}"}} {items[2]}\n')
return ans
最后就是写入啦,将list的每个item都写入到prom中,就大功告成啦
with open("firewall_session_topn.prom", 'w') as f:
for record in records:
f.write(record)
完整代码:
import re
import time
import paramiko
def send_command(shell, command):
shell.send(command + '\n')
time.sleep(10)
output = shell.recv(4096).decode()
if "Start a new statistics?[Y/N]:" in output:
shell.send('Y\n')
time.sleep(10)
output = shell.recv(4096).decode()
pattern = r'[-]{78}(.*?)[-]{78}'
matches = re.findall(pattern, output, re.DOTALL)
return matches[0]
def format_output(output, type):
ans = []
for line in output.split("\n"):
items = line.split()
if len(items) == 0:
continue
if not str.isdigit(items[0]):
continue
ans.append(f'firewall_session_topn{{ip="{items[1]}",type="{type}"}} {items[2]}\n')
return ans
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('ip_addr', username='username', password='password')
shell = ssh.invoke_shell()
records = []
# 外网访问内部 会话数TOP20-目的IP
output = send_command(shell, "display firewall topn destination-ip session-number source-zone dianxin top-number 20")
records += format_output(output,"out2in_dest")
# 外网访问内部 会话数TOP20-源IP
output = send_command(shell, "display firewall topn destination-ip session-number source-zone dianxin top-number 20")
records += format_output(output,"out2in_src")
# 内部访问外网 会话数TOP20-目的IP
output = send_command(shell, "display firewall topn destination-ip session-number source-zone trust_man top-number 20")
records += format_output(output,"in2out_dest")
# 内部访问外网 会话数TOP20-源IP
output = send_command(shell, "display firewall topn source-ip session-number source-zone trust_man top-number 20")
records += format_output(output,"in2out_src")
ssh.close()
with open("firewall_session_topn.prom", 'w') as f:
for record in records:
f.write(record)