zabbix批量主机维护脚本兼容性更新

最近做新老版本zabbix监控主机迁移发现zabbix6.0后api安全有了效大升级,批量主机维护脚本出现认证兼容性问题,以下为脚本更新token支持:`在这里插入代码片:

# /usr/bin/env python3
# -*- coding:utf-8 -*-
import requests
import json
import os
import re
from typing import List, Dict
import ipaddress## 用户配置区域
ZABBIX_URL = "http://[IP]/api_jsonrpc.php"  # Zabbix API 地址(根据不同版本api接口地址调整)
USE_API_TOKEN = True  # 是否使用 API Token 认证(True/False,token与传统认证方式二选一)
API_TOKEN = "[token]"  # zbx6创建固定Token时填写,zbx5.0以下用动态auth-token忽略
USERNAME = "[user]"  # 传统认证用户名(zbx6以下兼容,使用api-token认证时忽略)
PASSWORD = "[password]"  # 传统认证密码(zbx6以下兼容,使用api-token认证时忽略)
HOSTS_FILE = "serverlist.txt"  # 主机列表文件路径class ZabbixClient:def __init__(self, url: str, use_api_token: bool, token: str = None, username: str = None, password: str = None):self.url = urlself.use_api_token = use_api_tokenself.headers = {"Content-Type": "application/json-rpc"}# 配置认证if use_api_token:self.headers["Authorization"] = f"Bearer {token}"else:self.auth = self._login(username, password)def _login(self, username: str, password: str) -> str:"""传统认证获取Token"""payload = {"jsonrpc": "2.0","method": "user.login","params": {"user": username, "password": password},"id": 1}return self._send_request(payload, require_auth=False)["result"]def _send_request(self, payload: Dict, require_auth: bool = True) -> Dict:"""统一请求处理"""if require_auth and not self.use_api_token:payload["auth"] = self.authtry:response = requests.post(self.url,headers=self.headers,data=json.dumps(payload),timeout=10)response.raise_for_status()result = response.json()if "error" in result:error_info = result["error"]raise Exception(f"API错误 ({error_info['code']}): {error_info['message']}\n数据: {error_info.get('data', '')}")return resultexcept requests.exceptions.RequestException as e:raise Exception(f"请求失败: {str(e)}")def check_host_exists(self, hostname: str) -> bool:"""检查主机是否存在"""payload = {"jsonrpc": "2.0","method": "host.get","params": {"filter": {"host": hostname}, "output": ["hostid"]},"id": 2}result = self._send_request(payload, require_auth=True)return len(result["result"]) > 0def get_hostgroup(self, group_name: str) -> List[Dict]:"""获取主机组ID"""payload = {"jsonrpc": "2.0","method": "hostgroup.get","params": {"filter": {"name": [group_name]},"output": ["groupid"]},"id": 3}return self._send_request(payload, require_auth=True).get("result", [])def create_hostgroup(self, group_name: str) -> str:"""创建主机组并返回ID"""payload = {"jsonrpc": "2.0","method": "hostgroup.create","params": {"name": group_name},"id": 4}result = self._send_request(payload, require_auth=True)return result["result"]["groupids"][0]def get_template(self, template_name: str) -> List[Dict]:"""获取模板ID"""payload = {"jsonrpc": "2.0","method": "template.get","params": {"filter": {"host": [template_name]},"output": ["templateid"]},"id": 5}return self._send_request(payload, require_auth=True).get("result", [])def create_host(self, hostname: str, ip: str, groups: List[str], templates: List[str]) -> None:"""创建主机(带完整参数校验)"""self._validate_base_params(hostname, ip, groups, templates)if self.check_host_exists(hostname):print(f"主机 {hostname} 已存在,跳过")returngroup_ids = self._process_hostgroups(groups)template_ids = self._process_templates(templates)interface = self._build_interface(ip)payload = self._build_payload(hostname, interface, group_ids, template_ids)self._send_request(payload, require_auth=True)print(f"主机 {hostname} ({ip}) 创建成功")def _validate_base_params(self, hostname: str, ip: str, groups: List[str], templates: List[str]):"""基础参数校验"""if not hostname.strip():raise ValueError("主机名不可为空或仅包含空格")if not re.match(r'^[\w\-_.]+$', hostname):raise ValueError(f"主机名包含非法字符: {hostname}")if not self._is_valid_ip(ip):raise ValueError(f"无效IP地址: {ip}")if not groups or not all(groups):raise ValueError("主机组不可为空或包含空值")if not templates or not all(templates):raise ValueError("模板不可为空或包含空值")def _process_hostgroups(self, groups: List[str]) -> List[Dict]:"""处理主机组(创建不存在的组)"""group_ids = []for group in groups:group = group.strip()group_info = self.get_hostgroup(group)if not group_info:print(f"创建主机组 '{group}'...")group_id = self.create_hostgroup(group)group_ids.append({"groupid": group_id})else:group_ids.append({"groupid": group_info[0]["groupid"]})return group_idsdef _process_templates(self, templates: List[str]) -> List[Dict]:"""处理模板(校验存在性)"""template_ids = []for template in templates:template = template.strip()template_info = self.get_template(template)if not template_info:raise Exception(f"模板 '{template}' 不存在,请检查名称(区分大小写)")template_ids.append({"templateid": template_info[0]["templateid"]})return template_idsdef _build_interface(self, ip: str) -> Dict:"""构建接口参数(完整字段)"""return {"type": 1,          # Zabbix Agent接口"main": 1,          # 主接口"useip": 1,         # 使用IP地址"ip": ip,"port": "10050",     # 默认端口"dns": "",          # 可选字段,显式为空"ipmi_dns": "","username": "","password": ""}def _build_payload(self, hostname: str, interface: Dict, group_ids: List[Dict], template_ids: List[Dict]) -> Dict:"""构建完整请求参数(移除无效库存字段)"""return {"jsonrpc": "2.0","method": "host.create","params": {"host": hostname,"interfaces": [interface],"groups": group_ids,"templates": template_ids,"inventory_mode": 0  # 禁用自动发现,无需inventory字段},"id": 6}def _is_valid_ip(self, ip: str) -> bool:"""验证IP地址格式(支持IPv4/IPv6)"""try:ipaddress.ip_address(ip)return Trueexcept ValueError:print(f"无效IP格式: {ip}")return Falsedef main():"""主函数:批量导入主机"""try:# 初始化客户端if USE_API_TOKEN:zabbix = ZabbixClient(url=ZABBIX_URL,use_api_token=True,token=API_TOKEN)else:zabbix = ZabbixClient(url=ZABBIX_URL,use_api_token=False,username=USERNAME,password=PASSWORD)# 验证主机列表文件if not os.path.exists(HOSTS_FILE):raise FileNotFoundError(f"文件 {HOSTS_FILE} 不存在")# 处理主机列表with open(HOSTS_FILE, "r", encoding="utf-8") as f:for line_num, line in enumerate(f, 1):line = line.strip()if not line or line.startswith("#"):continuetry:# 解析行数据parts = line.split("#", 3)if len(parts) != 4:raise ValueError("字段数量错误,必须为4个(主机名#IP#主机组#模板)")hostname, ip, groups_str, templates_str = partsgroups = groups_str.split(",") if groups_str else []templates = templates_str.split(",") if templates_str else []# 创建主机zabbix.create_host(hostname, ip, groups, templates)except ValueError as ve:print(f"行 {line_num} 格式错误: {str(ve)},跳过")except Exception as e:print(f"行 {line_num} 处理失败: {str(e)}")except Exception as e:print(f"\n程序终止: {str(e)}")exit(1)if __name__ == "__main__":main()print("\n批量导入完成!")

注:输入文件 serverlist.txt 格式:
每行 主机名#IP地址#主机组1,主机组2#模板1,模板,示例:

web-server#192.168.1.1#Web Servers,Linux#Template OS Linux
db-server#192.168.1.2#DB Servers#Template OS Linux,Template MySQL

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/bicheng/82002.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java中static关键字深度解析:从入门到高阶实战

Java中static关键字深度解析:从入门到高阶实战 目录 static的本质与核心特性静态变量 vs 实例变量:底层对比静态方法的设计哲学与应用场景高级用法:突破常规的static技巧 4.1 静态代码块:类加载的“初始化引擎”4.2 静态内部类&…

基于RT-Thread的STM32F4开发第五讲——软件模拟I2C

文章目录 前言一、RT-Thread工程创建二、AT24C02三、函数编写1.I2C_soft.c2.I2C_soft.h3.main.h 四、效果展示五、资源分享总结 前言 本章是基于RT-Thread studio实现软件模拟I2C,开发板是正点原子的STM32F4探索者,使用的RT-Thread驱动是5.1.0&#xff0…

49、c# 能⽤foreach 遍历访问的对象需满足什么条件?

在 C# 中,要使用 foreach 循环遍历一个对象,该对象必须满足以下条件之一: 1. 实现 IEnumerable 或 IEnumerable 接口 非泛型版本:System.Collections.IEnumerable public class MyCollection : IEnumerable {private int[] _da…

推客小程序系统开发:全栈式技术解决方案与行业赋能实践​

​ 在数字化营销深度渗透各行业的当下,传统推广模式已难以满足企业精细化运营与高效获客的需求。专业的推客小程序系统凭借其强大的裂变传播能力与灵活的推广机制,成为企业构建私域流量池、提升推广效能的核心工具。我们基于多年技术沉淀与行业洞察&…

WPF布局系统详解:掌握界面设计的核心艺术

掌握界面设计的核心艺术 1. WPF布局系统概述2. Grid布局详解2.1 基本行列定义2.2 单元格定位与跨行跨列 3. StackPanel布局4. DockPanel布局5. WrapPanel与Canvas5.1 WrapPanel自动换行布局 5. Canvas绝对定位6. 布局嵌套与综合应用7. 布局性能优化8. 响应式布局技巧9. 实战&am…

labview实现LED流水灯的第一种方法

目的:写一个跑马灯程序,7个灯从左到右不停的轮流点亮,闪烁间隔由滑动条调节。 一、方法1:使用顺序结构 使用顺序结构,平铺式顺序结构与创建局部变量实现LED流水灯 具体步骤如下: 第一步,选择…

uniapp如何设置uni.request可变请求ip地址

文章目录 简介方法一:直接在请求URL中嵌入变量方法二:使用全局变量方法三:使用环境变量方法四:服务端配置方法五:使用配置文件(如config.js):总结 简介 在uni-app中,uni.request 用…

深度学习篇---LSTMADF轨迹预测

文章目录 前言LSTM 轨迹预测原理应用在行人轨迹预测方面在自动驾驶车辆的轨迹预测中优点缺点APF 轨迹预测原理应用在船舶运动规划在无人驾驶车辆避障轨迹跟踪优点缺点示例代码前言 本文简单介绍LSTM(长短期记忆网络)和ADF(人工势场法)这两种不同的轨迹预测方法。 LSTM 轨迹…

python实现Web请求与响应

目录 一:什么是Web请求与响应? 1:Web请求 2:Web响应 3:HTTP协议概述 4:常见的HTTP状态码包括: 二:python的requests库 1:安装requests库 2:发送GET请…

Unity使用sherpa-onnx实现说话人识别

网友软绵绵的面包人推荐,模型3dspeaker_speech_eres2net_base_200k_sv_zh-cn_16k-common.onnx的效果比3dspeaker_speech_eres2net_base_sv_zh-cn_3dspeaker_16k.onnx要好 具体代码 using System; using System.Collections.Generic; using System.IO; using Sherpa…

ElasticSearch-集群

本篇文章依据ElasticSearch权威指南进行实操和记录 1,空集群 即不包含任何节点的集群 集群大多数分为两类,主节点和数据节点 主节点 职责:主节点负责管理集群的状态,例如分配分片、添加和删除节点、监控节点故障等。它们不直接…

LG P9844 [ICPC 2021 Nanjing R] Paimon Segment Tree Solution

Description 给定序列 a ( a 1 , a 2 , ⋯ , a n ) a(a_1,a_2,\cdots,a_n) a(a1​,a2​,⋯,an​),有 m m m 次修改 ( l , r , v ) (l,r,v) (l,r,v): 对每个 i ∈ [ l , r ] i\in[l,r] i∈[l,r],令 a i ← a i v a_i\gets a_iv ai​←…

Google Prompt Tuning:文本嵌入优化揭秘

Google Research Prompt Tunin :from_embedded_string 在 Google Research 的 Prompt Tuning 项目代码库 中,from_embedded_string 函数主要用于基于字符串文本初始化提示词的嵌入向量,其调用场景通常与提示词优化或任务适配相关。 1. 核心代码位置 from_embedded_string …

网页 H5 微应用接入钉钉自动登录

ℹ️关于云审批 云审批(cloud approve) ,一款专为小微企业打造,支持多租户的在线审批神器。它简化了申请和审批流程,让您随时随地通过手机或电脑完成请款操作。员工一键提交申请,审批者即时响应&#xff0c…

idea无法识别Maven项目

把.mvn相关都删除了 导致Idea无法识别maven项目 或者 添加导入各个模块 最后把父模块也要导入

飞桨paddle import fluid报错【已解决】

跟着飞桨的安装指南安装了paddle之后 pip install paddlepaddle有一个验证: import paddle.fluid as fluid fluid.install check.run check()报错情况如下,但是我在pip list中,确实看到了paddle安装上了 我import paddle别的包&#xff0c…

现代化SQLite的构建之旅——解析开源项目Limbo

现代化SQLite的构建之旅——解析开源项目Limbo 在当今飞速发展的技术世界中,轻量级且功能强大的数据库已成为开发者的得力助手。当我们谈论轻量级数据库时,SQLite无疑是一个举足轻重的名字。然而,随着技术的进步,我们对数据库的需求也变得更加多样化。这正是Limbo项目诞生…

MinIO:从入门到精通,解锁云原生存储的奥秘

一、引言:为什么 MinIO 正在重塑存储世界? 在云计算和大数据时代,传统存储系统面临扩展性差、成本高、兼容性不足等挑战。MinIO 凭借其 S3 兼容性、分布式架构、高性能存储 等特性,成为企业构建现代化存储基础设施的首选。 本文…

vscode怎么关闭自动定位文件

关闭自动定位文件功能 方式1 在设置中搜索: explorer.autoReveal 方式2 直接在settings.json中增加"explorer.autoReveal": false 添加类似jetbrains IDE的文件定位功能 可以直接安装插件市场搜索niushuaibing.vs-location, 安装后会有文件定位按钮, 点击后即可…

学习路之uniapp--unipush2.0推送功能--给自己发通知

学习路之uniapp--unipush2.0推送功能--给自己发通知 一、绑定云空间及创建云函数二、编写发送界面三、效果后期展望: 一、绑定云空间及创建云函数 package.json {"name": "server-push","dependencies": {},"main": "…