Python远程执行命令编写Nagios RAID状态监控插件方案咨询
Nagios远程检测RAID状态的提权方案与脚本实现
核心提权实现(最高效安全的生产标准方案)
获取RAID状态需要root权限,不要使用root直连SSH、给二进制加SUID这类高风险方案,正确实现步骤如下:
- 在被监控主机创建专用的监控账号(例如
nagios_check),配置监控服务器到该账号的SSH密钥免密登录,同时禁止该账号的交互式登录权限 - 在被监控主机用
visudo命令编辑sudo规则(该命令会自动做语法校验,避免配置错误导致sudo功能失效),添加如下行,给监控账号开放单条命令的免密sudo权限:
nagios_check ALL=(root) NOPASSWD: /opt/MegaRAID/MegaCli/MegaCli64 -ShowSummary -a0
注意:规则必须写全命令的绝对路径和固定参数,不要使用通配符,避免出现权限逃逸漏洞
- 后续远程执行命令时,在原MegaCli命令前加
sudo即可正常获取输出,不需要输入密码,权限边界清晰无额外风险。
现有脚本的问题修正
你提供的初稿存在几处会导致运行失效的错误,需要调整:
- 语法错误:
ssh.stdoutreadlines()为错误写法,正确方法是ssh.stdout.readlines();直接拼接SSH命令字符串存在命令注入风险,应该用列表形式传参给subprocess模块 - 逻辑错误:原状态判断语句
elif (active) or (online) or (k) in (check)存在优先级问题,会直接判定为真,无论输出是否匹配都会返回OK状态;读取的SSH输出为bytes类型,直接做字符串匹配会出现漏判 - 规范问题:Nagios插件要求标准输出只返回最终状态字符串,多余的调试打印(比如你写的
print(args))会导致Nagios无法正常识别状态;未做超时、执行异常处理,网络波动时会导致插件卡死 - 冗余问题:导入了未使用的os、socket模块,多余的
str()类型转换可以删除
修正后可直接使用的插件脚本
#!/usr/bin/env python3 import sys import argparse import subprocess # Nagios标准返回码,固定不可修改 OK = 0 WARNING = 1 CRITICAL = 2 UNKNOWN = 4 # 状态匹配关键词 KEYWORD_DEGRADED = "Degraded" KEYWORD_FAILED = "Failed" KEYWORDS_OK = ["Active", "Online", "OK"] if __name__ == "__main__": parser = argparse.ArgumentParser(description='LSI RAID控制器状态Nagios检测插件') parser.add_argument("--user", "-U", required=True, help="远程SSH连接用户名") parser.add_argument("--hostname", "-H", required=True, help="被监控主机地址") args = parser.parse_args() # 构造SSH执行命令,列表传参避免命令注入 ssh_exec_cmd = [ "ssh", "-o", "StrictHostKeyChecking=accept-new", f"{args.user}@{args.hostname}", "sudo", "/opt/MegaRAID/MegaCli/MegaCli64", "-ShowSummary", "-a0" ] try: exec_result = subprocess.run( ssh_exec_cmd, capture_output=True, timeout=30, check=True ) # 统一转小写做匹配,规避大小写差异导致的漏判 raid_output = exec_result.stdout.decode('utf-8', errors='ignore').lower() except subprocess.CalledProcessError as e: err_msg = e.stderr.decode('utf-8', errors='ignore').strip() print(f"UNKNOWN: 远程命令执行失败, 错误信息: {err_msg}") sys.exit(UNKNOWN) except subprocess.TimeoutExpired: print("UNKNOWN: 远程命令执行超时(30秒)") sys.exit(UNKNOWN) except Exception as e: print(f"UNKNOWN: 执行异常: {str(e)}") sys.exit(UNKNOWN) # 按优先级判断状态 if KEYWORD_FAILED.lower() in raid_output: print("CRITICAL: RAID阵列存在故障硬盘,阵列已失效!") sys.exit(CRITICAL) elif KEYWORD_DEGRADED.lower() in raid_output: print("WARNING: RAID阵列处于降级状态,请及时排查硬盘健康度") sys.exit(WARNING) elif KEYWORDS_OK[0].lower() in raid_output and KEYWORDS_OK[1].lower() in raid_output or KEYWORDS_OK[2].lower() in raid_output: print("OK: RAID控制器、阵列状态均正常") sys.exit(OK) else: print("UNKNOWN: 无法识别RAID返回内容,请手动登录主机排查") sys.exit(UNKNOWN)
部署注意事项
- 给脚本添加可执行权限:
chmod +x check_lsi_raid.py,放到Nagios的插件目录下即可按常规插件方式配置监控 - SSH参数里加了
StrictHostKeyChecking=accept-new,可以自动接受首次连接的主机密钥,避免因为host key校验交互导致插件卡住 - 被监控端sudo规则配置完成后,执行
visudo -c校验语法,确认返回解析成功再上线
内容的提问来源于stack exchange,提问作者Alex Noel
相关产品推荐
相关产品推荐

