first commit
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"id": "2945e4d9",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"with open(\"./result.txt\", \"r\") as f:\n",
|
||||
" data = f.readlines()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"id": "0cadbfac",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"mac_data = {}\n",
|
||||
"for item in data:\n",
|
||||
" if \"(hex)\" in item:\n",
|
||||
" tem = item.split(\"(hex)\")\n",
|
||||
" mac_head = tem[0].strip()\n",
|
||||
" mac_info = tem[1].strip()\n",
|
||||
" mac_data[mac_head] = mac_info"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"id": "f4b26aba",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import json"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"id": "547be298",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"with open(\"./mac_data.json\", \"r\") as f:\n",
|
||||
" f.read()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"id": "022741d0",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"0XEA.0XA0.0XED.0XFF.0XFE.0X5E.0X17.0X14."
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"for item in \"234.160.237.255.254.94.23.20\".split(\".\"):\n",
|
||||
" print(hex(int(item)).upper(), end=\".\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "d23bcc03",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "base",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.12.4"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
+37657
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,52 @@
|
||||
import logging
|
||||
import os
|
||||
from logging.handlers import RotatingFileHandler
|
||||
|
||||
|
||||
def mylog(log_file="zabbix.log", max_bytes=10 * 1024 * 1024, backup_count=5):
|
||||
"""
|
||||
配置日志记录器,输出到/home/zabbix目录且不显示在控制台
|
||||
|
||||
参数:
|
||||
log_file: 日志文件名 (默认: zabbix.log)
|
||||
max_bytes: 单个日志文件最大字节 (默认: 10MB)
|
||||
backup_count: 保留的备份文件数 (默认: 5)
|
||||
"""
|
||||
# 创建日志目录
|
||||
log_dir = "./"
|
||||
os.makedirs(log_dir, exist_ok=True) # 自动创建目录[1,4](@ref)
|
||||
|
||||
# 完整的日志文件路径
|
||||
log_path = os.path.join(log_dir, log_file)
|
||||
|
||||
# 创建记录器
|
||||
logger = logging.getLogger("ZabbixLogger")
|
||||
logger.setLevel(logging.DEBUG) # 设置最低日志级别
|
||||
|
||||
# 配置日志格式
|
||||
formatter = logging.Formatter(
|
||||
"%(asctime)s - %(filename)s:%(lineno)d - %(levelname)s - %(message)s",
|
||||
datefmt="%Y-%m-%d %H:%M:%S",
|
||||
)
|
||||
|
||||
# 创建文件处理器(带日志轮转功能)[1,3](@ref)
|
||||
file_handler = RotatingFileHandler(
|
||||
log_path, maxBytes=max_bytes, backupCount=backup_count, encoding="utf-8"
|
||||
)
|
||||
file_handler.setFormatter(formatter)
|
||||
file_handler.setLevel(logging.INFO) # 文件日志级别
|
||||
|
||||
# 移除所有现有处理器(避免重复)
|
||||
if logger.hasHandlers():
|
||||
logger.handlers.clear()
|
||||
|
||||
# 添加文件处理器(不添加StreamHandler避免控制台输出)[6,8](@ref)
|
||||
logger.addHandler(file_handler)
|
||||
|
||||
# 禁用向父logger传播(避免root logger输出到控制台)[9](@ref)
|
||||
logger.propagate = False
|
||||
|
||||
return logger
|
||||
|
||||
|
||||
# 使用示例
|
||||
@@ -0,0 +1,204 @@
|
||||
#!/usr/bin/env /opt/miniconda3/envs/py37/bin/python
|
||||
import sys
|
||||
import json
|
||||
from pysnmp.hlapi import *
|
||||
from mylog import mylog as mylog
|
||||
|
||||
log = mylog("./zabbix.log")
|
||||
|
||||
|
||||
def snmp_walk(host, oid, format="str", strip_prefix=True, community="zabbix"):
|
||||
res = {}
|
||||
# 使用正确的 nextCmd 函数
|
||||
for errorIndication, errorStatus, errorIndex, varBinds in nextCmd(
|
||||
SnmpEngine(),
|
||||
CommunityData(community),
|
||||
UdpTransportTarget((host, 161), timeout=4.0, retries=3),
|
||||
ContextData(),
|
||||
ObjectType(ObjectIdentity(oid)),
|
||||
lookupMib=False,
|
||||
lexicographicMode=False,
|
||||
):
|
||||
if errorIndication:
|
||||
raise ConnectionError(
|
||||
f'SNMP error: "{str(errorIndication)}". Status={str(errorStatus)}'
|
||||
)
|
||||
elif errorStatus:
|
||||
raise ConnectionError(
|
||||
f'SNMP error: "{str(errorStatus)}" at index {str(errorIndex)}'
|
||||
)
|
||||
else:
|
||||
for varBind in varBinds:
|
||||
oid_str = str(varBind[0])
|
||||
value = varBind[1]
|
||||
|
||||
# 如果指定了去除前缀
|
||||
if strip_prefix:
|
||||
oid_str = oid_str.replace(oid, "", 1).lstrip(".")
|
||||
|
||||
# 根据格式处理值
|
||||
if format == "hex":
|
||||
res[oid_str] = value.asOctets().hex().upper()
|
||||
elif format == "str":
|
||||
res[oid_str] = str(value)
|
||||
else:
|
||||
res[oid_str] = value
|
||||
return res
|
||||
|
||||
|
||||
def machex(mac_part):
|
||||
"""将OID格式的MAC转换为标准格式"""
|
||||
parts = [int(x) for x in mac_part.split(".")]
|
||||
return "-".join(f"{x:02x}" for x in parts[-6:])
|
||||
|
||||
|
||||
def read_ipv4_from_oid_tail(oid, with_len=True):
|
||||
parts = [int(x) for x in oid.split(".")]
|
||||
if with_len:
|
||||
assert parts[-5] == 4 # number of elements
|
||||
return ".".join([str(x) for x in parts[-4:]])
|
||||
|
||||
|
||||
from datetime import timedelta
|
||||
|
||||
|
||||
def ms_to_timedelta(milliseconds):
|
||||
delta = timedelta(milliseconds=milliseconds)
|
||||
hours = delta.seconds // 3600
|
||||
minutes = (delta.seconds % 3600) // 60
|
||||
seconds = delta.seconds % 60
|
||||
return f"{hours}:{minutes:02d}:{seconds:02d}"
|
||||
|
||||
|
||||
def format_mac(mac_str: str) -> str:
|
||||
# 每2个字符分割一次,生成子字符串列表
|
||||
segments = [mac_str[i : i + 2] for i in range(0, len(mac_str), 2)]
|
||||
# 用连字符连接子字符串,并添加末尾换行符
|
||||
return "-".join(segments)
|
||||
|
||||
|
||||
def main():
|
||||
log.info(str(sys.argv))
|
||||
if len(sys.argv) < 4:
|
||||
print("Usage: ./switch_monitor.py <mode> <switch_ip> <community> [port]")
|
||||
sys.exit(1)
|
||||
|
||||
mode = sys.argv[1]
|
||||
switch_ip = sys.argv[2]
|
||||
community = sys.argv[3]
|
||||
port_filter = sys.argv[4] if len(sys.argv) >= 5 else None
|
||||
log.info(sys.argv)
|
||||
# 1. 获取端口映射表
|
||||
port_mapping = {}
|
||||
dot1dBasePortIfIndex = snmp_walk(
|
||||
switch_ip, "1.3.6.1.2.1.17.1.4.1.2", "int", True, community
|
||||
)
|
||||
ifDescr = snmp_walk(switch_ip, "1.3.6.1.2.1.2.2.1.2", "str", True, community)
|
||||
for bridge_index, if_index in dot1dBasePortIfIndex.items():
|
||||
if str(if_index) in ifDescr:
|
||||
port_mapping[str(bridge_index)] = ifDescr[str(if_index)]
|
||||
# 2. 获取MAC表和ip地址
|
||||
mac_table = snmp_walk(switch_ip, "1.3.6.1.2.1.17.4.3.1.2", "int", True, community)
|
||||
|
||||
# 3. 统计端口MAC数量
|
||||
port_counts = {}
|
||||
mac_details = {}
|
||||
for mac_oid, bridge_index in mac_table.items():
|
||||
standard_mac = machex(mac_oid).upper()
|
||||
if str(bridge_index) in port_mapping:
|
||||
port_name = port_mapping[str(bridge_index)]
|
||||
port_counts[port_name] = port_counts.get(port_name, 0) + 1
|
||||
|
||||
if mode == "list":
|
||||
atPhysAddress = snmp_walk(
|
||||
switch_ip, "1.3.6.1.2.1.3.1.1.2", "hex", True, community
|
||||
)
|
||||
oid_mac = snmp_walk(
|
||||
switch_ip,
|
||||
"1.3.6.1.2.1.55.1.12.1.2.719.254.128.0.0.0.0.0.0",
|
||||
"hex",
|
||||
True,
|
||||
community,
|
||||
)
|
||||
oid_hour = snmp_walk(
|
||||
switch_ip,
|
||||
"1.3.6.1.2.1.55.1.12.1.5.719.254.128.0.0.0.0.0.0",
|
||||
"str",
|
||||
True,
|
||||
community,
|
||||
)
|
||||
mac_time = {}
|
||||
# ms_to_timedelta
|
||||
for oid, mac in oid_mac.items():
|
||||
f_mac = format_mac(mac)
|
||||
time = oid_hour.get(oid, "0")
|
||||
time = ms_to_timedelta(int(time + "0"))
|
||||
mac_time[f_mac] = time
|
||||
mac_ip_table = {}
|
||||
for oid, mac in atPhysAddress.items():
|
||||
ip = read_ipv4_from_oid_tail(oid, with_len=False)
|
||||
mac_ip_table[format_mac(mac)] = ip
|
||||
for mac_oid, bridge_index in mac_table.items():
|
||||
standard_mac = machex(mac_oid).upper()
|
||||
if str(bridge_index) in port_mapping:
|
||||
port_name = port_mapping[str(bridge_index)]
|
||||
ip = mac_ip_table.get(standard_mac, False)
|
||||
mac_details.setdefault(port_name, []).append(
|
||||
{
|
||||
"ip": ip,
|
||||
"mac": standard_mac,
|
||||
"time": mac_time.get(standard_mac, "N/A"),
|
||||
}
|
||||
)
|
||||
# 3. 如果指定了端口过滤,进行过滤
|
||||
# 4. 根据模式输出
|
||||
if mode == "discovery":
|
||||
# 输出端口自动发现数据
|
||||
discovery = []
|
||||
for port in port_counts.keys():
|
||||
discovery.append(
|
||||
{
|
||||
"{#SWITCH_IP}": switch_ip,
|
||||
"{#PORT_NAME}": port,
|
||||
"{#COMMUNITY}": community,
|
||||
}
|
||||
)
|
||||
print(json.dumps({"data": discovery}))
|
||||
|
||||
elif mode == "count":
|
||||
# 输出特定端口的MAC数量
|
||||
if not port_filter:
|
||||
print("0")
|
||||
return
|
||||
|
||||
print(str(port_counts.get(port_filter, 0)))
|
||||
|
||||
elif mode == "list":
|
||||
# 输出特定端口的MAC列表
|
||||
if not port_filter:
|
||||
print("[]")
|
||||
return
|
||||
if port_filter in mac_details:
|
||||
pass
|
||||
print(json.dumps(mac_details[port_filter]))
|
||||
else:
|
||||
print("[]")
|
||||
|
||||
elif mode == "details":
|
||||
# 输出详细MAC信息(用于调试)
|
||||
details = {}
|
||||
for port, macs in mac_details.items():
|
||||
details[port] = {"count": len(macs), "macs": macs}
|
||||
print(json.dumps(details))
|
||||
log.info(json.dumps(details))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.argv = [
|
||||
"/usr/lib/zabbix/externalscripts/switch_monitor.py",
|
||||
"list",
|
||||
"192.168.0.112",
|
||||
"zabbix",
|
||||
"GigabitEthernet1/0/5",
|
||||
]
|
||||
main()
|
||||
+253
@@ -0,0 +1,253 @@
|
||||
#!/usr/bin/env /opt/miniconda3/envs/py37/bin/python
|
||||
import sys
|
||||
import json
|
||||
from datetime import timedelta
|
||||
from pysnmp.hlapi import *
|
||||
from mylog import mylog as mylog
|
||||
|
||||
log = mylog("./zabbix.log")
|
||||
|
||||
|
||||
class SNMPHelper:
|
||||
"""封装SNMP操作的工具类"""
|
||||
|
||||
@staticmethod
|
||||
def snmp_walk(host, oid, format="str", strip_prefix=True, community="zabbix"):
|
||||
"""执行SNMP walk操作并返回处理后的数据"""
|
||||
res = {}
|
||||
for errorIndication, errorStatus, errorIndex, varBinds in nextCmd(
|
||||
SnmpEngine(),
|
||||
CommunityData(community),
|
||||
UdpTransportTarget((host, 161), timeout=4.0, retries=3),
|
||||
ContextData(),
|
||||
ObjectType(ObjectIdentity(oid)),
|
||||
lookupMib=False,
|
||||
lexicographicMode=False,
|
||||
):
|
||||
if errorIndication:
|
||||
raise ConnectionError(
|
||||
f'SNMP error: "{errorIndication}". Status={errorStatus}'
|
||||
)
|
||||
elif errorStatus:
|
||||
raise ConnectionError(
|
||||
f'SNMP error: "{errorStatus}" at index {errorIndex}'
|
||||
)
|
||||
|
||||
for varBind in varBinds:
|
||||
oid_str = str(varBind[0])
|
||||
value = varBind[1]
|
||||
|
||||
# 处理OID前缀
|
||||
if strip_prefix:
|
||||
oid_str = oid_str.replace(oid, "", 1).lstrip(".")
|
||||
|
||||
# 格式化返回值
|
||||
if format == "hex":
|
||||
res[oid_str] = value.asOctets().hex().upper()
|
||||
elif format == "str":
|
||||
res[oid_str] = str(value)
|
||||
else:
|
||||
res[oid_str] = value
|
||||
return res
|
||||
|
||||
|
||||
class MACUtils:
|
||||
"""MAC地址相关工具函数"""
|
||||
|
||||
@staticmethod
|
||||
def machex(mac_part):
|
||||
"""将OID格式的MAC转换为标准格式"""
|
||||
parts = [int(x) for x in mac_part.split(".")]
|
||||
return "-".join(f"{x:02x}" for x in parts[-6:]).upper()
|
||||
|
||||
@staticmethod
|
||||
def format_mac(mac_str: str) -> str:
|
||||
"""格式化MAC地址字符串"""
|
||||
segments = [mac_str[i : i + 2] for i in range(0, len(mac_str), 2)]
|
||||
return "-".join(segments).upper()
|
||||
|
||||
|
||||
class NetworkUtils:
|
||||
"""网络相关工具函数"""
|
||||
|
||||
@staticmethod
|
||||
def read_ipv4_from_oid(oid):
|
||||
"""从OID中提取IPv4地址"""
|
||||
parts = [int(x) for x in oid.split(".")]
|
||||
return ".".join(str(x) for x in parts[-4:])
|
||||
|
||||
@staticmethod
|
||||
def ms_to_timedelta(milliseconds):
|
||||
"""毫秒时间转换为可读的时间格式"""
|
||||
delta = timedelta(milliseconds=int(milliseconds))
|
||||
hours = delta.seconds // 3600
|
||||
minutes = (delta.seconds % 3600) // 60
|
||||
seconds = delta.seconds % 60
|
||||
return f"{hours}:{minutes:02d}:{seconds:02d}"
|
||||
|
||||
|
||||
class SwitchMonitor:
|
||||
def __init__(self, switch_ip, community):
|
||||
self.switch_ip = switch_ip
|
||||
self.community = community
|
||||
self.port_mapping = {}
|
||||
self.mac_table = {}
|
||||
self.port_counts = {}
|
||||
self.mac_details = {}
|
||||
|
||||
# 初始化基础数据
|
||||
self._init_port_mapping()
|
||||
self._init_mac_table()
|
||||
|
||||
def _init_port_mapping(self):
|
||||
"""初始化端口映射数据"""
|
||||
dot1dBasePortIfIndex = SNMPHelper.snmp_walk(
|
||||
self.switch_ip, "1.3.6.1.2.1.17.1.4.1.2", "int", True, self.community
|
||||
)
|
||||
ifDescr = SNMPHelper.snmp_walk(
|
||||
self.switch_ip, "1.3.6.1.2.1.2.2.1.2", "str", True, self.community
|
||||
)
|
||||
|
||||
for bridge_index, if_index in dot1dBasePortIfIndex.items():
|
||||
if str(if_index) in ifDescr:
|
||||
self.port_mapping[bridge_index] = ifDescr[str(if_index)]
|
||||
|
||||
def _init_mac_table(self):
|
||||
"""初始化MAC表并统计各端口MAC数量"""
|
||||
self.mac_table = SNMPHelper.snmp_walk(
|
||||
self.switch_ip, "1.3.6.1.2.1.17.4.3.1.2", "int", True, self.community
|
||||
)
|
||||
|
||||
for mac_oid, bridge_index in self.mac_table.items():
|
||||
if str(bridge_index) in self.port_mapping:
|
||||
port_name = self.port_mapping[str(bridge_index)]
|
||||
self.port_counts[port_name] = self.port_counts.get(port_name, 0) + 1
|
||||
|
||||
def get_mac_details(self):
|
||||
"""获取详细的MAC地址信息(IP和在线时间)"""
|
||||
if not hasattr(self, "_mac_details"):
|
||||
self._mac_details = {}
|
||||
atPhysAddress = SNMPHelper.snmp_walk(
|
||||
self.switch_ip, "1.3.6.1.2.1.3.1.1.2", "hex", True, self.community
|
||||
)
|
||||
|
||||
# 获取MAC时间信息
|
||||
oid_mac = SNMPHelper.snmp_walk(
|
||||
self.switch_ip,
|
||||
"1.3.6.1.2.1.55.1.12.1.2.719.254.128.0.0.0.0.0.0",
|
||||
"hex",
|
||||
True,
|
||||
self.community,
|
||||
)
|
||||
oid_hour = SNMPHelper.snmp_walk(
|
||||
self.switch_ip,
|
||||
"1.3.6.1.2.1.55.1.12.1.5.719.254.128.0.0.0.0.0.0",
|
||||
"str",
|
||||
True,
|
||||
self.community,
|
||||
)
|
||||
|
||||
mac_time = {}
|
||||
for oid, mac in oid_mac.items():
|
||||
time_val = oid_hour.get(oid, "0")
|
||||
try:
|
||||
# 避免字符串拼接方式转换时间
|
||||
formatted_time = NetworkUtils.ms_to_timedelta(time_val + "0")
|
||||
except ValueError:
|
||||
formatted_time = "N/A"
|
||||
mac_time[MACUtils.format_mac(mac)] = formatted_time
|
||||
# 构建MAC-IP映射
|
||||
mac_ip_table = {}
|
||||
for oid, mac in atPhysAddress.items():
|
||||
try:
|
||||
ip = NetworkUtils.read_ipv4_from_oid(oid)
|
||||
mac_ip_table[MACUtils.format_mac(mac)] = ip
|
||||
except (ValueError, IndexError):
|
||||
continue
|
||||
# 组织MAC详细信息
|
||||
for mac_oid, bridge_index in self.mac_table.items():
|
||||
standard_mac = MACUtils.machex(mac_oid)
|
||||
port_name = self.port_mapping.get(str(bridge_index))
|
||||
|
||||
if port_name:
|
||||
self._mac_details.setdefault(port_name, []).append(
|
||||
{
|
||||
"ip": mac_ip_table.get(standard_mac, "N/A"),
|
||||
"mac": standard_mac,
|
||||
"time": mac_time.get(standard_mac, "N/A"),
|
||||
}
|
||||
)
|
||||
|
||||
return self._mac_details
|
||||
|
||||
|
||||
def main():
|
||||
log.info(f"启动参数: {sys.argv}")
|
||||
|
||||
# 参数验证
|
||||
if len(sys.argv) < 4:
|
||||
print("Usage: ./switch_monitor.py <mode> <switch_ip> <community> [port]")
|
||||
sys.exit(1)
|
||||
|
||||
mode = sys.argv[1]
|
||||
switch_ip = sys.argv[2]
|
||||
community = sys.argv[3]
|
||||
port_filter = sys.argv[4] if len(sys.argv) >= 5 else None
|
||||
|
||||
try:
|
||||
monitor = SwitchMonitor(switch_ip, community)
|
||||
|
||||
# 处理不同模式
|
||||
if mode == "discovery":
|
||||
# 输出端口自动发现数据
|
||||
discovery = [
|
||||
{
|
||||
"{#SWITCH_IP}": switch_ip,
|
||||
"{#PORT_NAME}": port,
|
||||
"{#COMMUNITY}": community,
|
||||
}
|
||||
for port in monitor.port_counts
|
||||
]
|
||||
print(json.dumps({"data": discovery}))
|
||||
|
||||
elif mode == "count":
|
||||
# 输出特定端口的MAC数量
|
||||
if not port_filter:
|
||||
print("0")
|
||||
return
|
||||
|
||||
count = monitor.port_counts.get(port_filter, 0)
|
||||
print(str(count))
|
||||
|
||||
elif mode == "list":
|
||||
# 输出特定端口的MAC列表
|
||||
mac_details = monitor.get_mac_details()
|
||||
result = mac_details.get(port_filter, []) if port_filter else []
|
||||
print(json.dumps(result))
|
||||
|
||||
elif mode == "details":
|
||||
# 输出详细MAC信息(用于调试)
|
||||
details = {
|
||||
port: {"count": len(macs), "macs": macs}
|
||||
for port, macs in monitor.get_mac_details().items()
|
||||
}
|
||||
print(json.dumps(details))
|
||||
log.info(f"详细MAC信息: {json.dumps(details)}")
|
||||
|
||||
except Exception as e:
|
||||
log.error(f"处理时发生错误: {str(e)}")
|
||||
if mode in ["discovery", "details"]:
|
||||
print(json.dumps({}))
|
||||
else:
|
||||
print("0" if mode == "count" else "[]")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.argv = [
|
||||
"/usr/lib/zabbix/externalscripts/switch_monitor.py",
|
||||
"count",
|
||||
"192.168.0.112",
|
||||
"zabbix",
|
||||
"GigabitEthernet1/0/5",
|
||||
]
|
||||
main()
|
||||
Reference in New Issue
Block a user