第8章:插件体系详解
第8章:插件体系详解
插件是 Nagios 的灵魂,决定了监控系统的能力边界。本章全面介绍 Nagios 插件体系,包括官方插件、社区插件、自定义插件开发、插件分类和最佳实践。
一、插件体系概览
1.1 插件生态架构
┌─────────────────────────────────────────────────────────────┐
│ Nagios 插件生态 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 官方插件 (nagios-plugins) │
│ ├── 基础检查:ping, tcp, ssh, dns, http │
│ ├── 系统检查:disk, load, users, procs, swap, uptime │
│ ├── 网络检查:smtp, pop3, imap, ntp, ldap │
│ ├── 数据库检查:mysql, pgsql, oracle │
│ └── 应用检查:fping, game, dig, rpc │
│ │
│ 社区插件 (Nagios Exchange) │
│ ├── check_mk - 综合检查套件 │
│ ├── check_nrpe - NRPE 远程检查客户端 │
│ ├── check_snmp - SNMP 检查 │
│ ├── check_mysql_health - MySQL 深度检查 │
│ └── 3000+ 更多插件... │
│ │
│ 自定义插件 │
│ ├── Shell 脚本 │
│ ├── Python 脚本 │
│ ├── Perl 脚本 │
│ ├── C 程序 │
│ └── 任何可执行程序 │
│ │
└─────────────────────────────────────────────────────────────┘
1.2 插件运行机制
Nagios Core
│
│ fork() 子进程执行
▼
┌──────────────────┐
│ 插件进程 │
│ check_xxx -args │
└──────────────────┘
│
├─ 标准输出 (stdout) → 状态文本 + 性能数据
│
└─ 退出码 (exit code) → 0=OK, 1=WARNING, 2=CRITICAL, 3=UNKNOWN
二、官方插件详解
2.1 基础网络检查
| 插件 | 用途 | 关键参数 |
|---|
check_ping | ICMP Ping 检查 | -H host -w warn -c crit -p packets |
check_tcp | TCP 端口检查 | -H host -p port -t timeout |
check_udp | UDP 端口检查 | -H host -p port -s send -e expect |
check_ssh | SSH 服务检查 | -H host -p port -t timeout |
check_dns | DNS 解析检查 | -H hostname -s server |
check_dig | DNS Dig 检查 | -H host -l lookup -T type |
check_fping | 高效 Ping 检查 | -H host -w warn -c crit |
check_smtp | SMTP 服务检查 | -H host -p port -e expect |
check_pop3 | POP3 服务检查 | -H host -p port -e expect |
check_imap | IMAP 服务检查 | -H host -p port -e expect |
check_ntp | NTP 时间检查 | -H host -w warn -c crit |
check_ntp_peer | NTP 对等检查 | -H host -w warn -c crit |
check_ldap | LDAP 服务检查 | -H host -b base -p port |
2.2 Web 服务检查
# check_http 常用参数
check_http -H host [-I IP] [-p port] [-u URL] [-S] [-e code] [-s string]
[-a user:pass] [-A auth] [-P post] [-m min:max]
[-w warn] [-c crit] [-t timeout] [--sni] [-C days]
# HTTP 基本检查
check_http -H www.example.com
# HTTPS 检查
check_http -H www.example.com -S -p 443
# 指定 URL 路径
check_http -H www.example.com -u /api/health
# 响应码检查
check_http -H www.example.com -e 200,301,302
# 内容检查
check_http -H www.example.com -s "Welcome"
# 响应时间阈值
check_http -H www.example.com -w 5 -c 10
# SSL 证书过期检查(提前 30 天警告,7 天严重)
check_http -H www.example.com -S -C 30,7
# Basic 认证
check_http -H www.example.com -a user:password
# POST 请求
check_http -H www.example.com -P "key=value" -u /api/submit
# 虚拟主机
check_http -H www.example.com -I 192.168.1.100 --sni
2.3 系统资源检查
# 磁盘使用率
check_disk -w 20% -c 10% -p /
check_disk -w 20% -c 10% -p /home -p /var -p /tmp
check_disk -w 1000 -c 500 -p / # 使用 MB 阈值
# CPU 负载(1/5/15 分钟)
check_load -w 5,4,3 -c 10,8,6
# 用户数
check_users -w 5 -c 10
# 进程数
check_procs -w 150 -c 200
check_procs -w 5:10 -c 1:20 -s httpd # 指定进程名和范围
# Swap 使用率
check_swap -w 50% -c 25%
# 系统运行时间
check_uptime
# 文件句柄
check_file_handles -w 80% -c 95%
2.4 数据库检查
# MySQL 检查
check_mysql -H localhost -u monitoring -p password -d database_name
check_mysql_query -H localhost -u monitoring -p password -q "SELECT COUNT(*) FROM users" -w 100 -c 200
# PostgreSQL 检查
check_pgsql -H localhost -l monitoring -p 5432
# Oracle 检查(需要 check_oracle_health 插件)
check_oracle_health --connect database --mode connection-time --user monitor --password secret
2.5 SNMP 检查
# SNMP 获取单个值
check_snmp -H 192.168.1.1 -C public -o sysUpTime.0
# SNMP 带阈值
check_snmp -H 192.168.1.1 -C public -o ifInOctets.1 -w 1000000 -c 2000000
# SNMP 接口状态
check_snmp -H 192.168.1.1 -C public -o ifOperStatus.1 -s 1
# SNMP CPU 使用率(OID 因厂商而异)
check_snmp -H 192.168.1.1 -C public -o 1.3.6.1.4.1.2021.11.9.0 -w 80 -c 95
# SNMP 内存使用率
check_snmp -H 192.168.1.1 -C public -o 1.3.6.1.4.1.2021.4.6.0 -w 80 -c 95
三、社区插件推荐
3.1 Nagios Exchange 热门插件
| 插件 | 用途 | 语言 | 链接 |
|---|
check_mk | 综合检查套件 | Python | check-mk.org |
check_nrpe | NRPE 客户端 | C | nagios.org |
check_mysql_health | MySQL 深度检查 | Perl | labs.consol.de |
check_oracle_health | Oracle 深度检查 | Perl | labs.consol.de |
check_mongodb | MongoDB 检查 | Python | github |
check_redis | Redis 检查 | Python | github |
check_elasticsearch | Elasticsearch 检查 | Python | github |
check_docker | Docker 容器检查 | Shell | github |
check_ssl_cert | SSL 证书详细检查 | Shell | github |
check_puppet | Puppet 状态检查 | Ruby | github |
check_raid | RAID 状态检查 | Perl | github |
check_iostat | I/O 统计检查 | Shell | github |
check_mem | 内存使用检查 | Shell | github |
check_logfiles | 日志文件检查 | Perl | consol.de |
check_multi | 多检查聚合 | Perl | github |
check_url | URL 内容检查 | Perl | github |
3.2 安装社区插件
# 方式一:手动下载
cd /usr/local/nagios/libexec/
wget https://example.com/check_custom
chmod +x check_custom
# 方式二:使用包管理器
yum install -y nagios-plugins-all # EPEL 源
# 方式三:编译安装
cd /tmp
git clone https://github.com/nagios-plugins/nagios-plugins.git
cd nagios-plugins
./tools/setup
./configure
make && sudo make install
四、自定义插件开发
4.1 插件开发规范
- 必须遵循退出码规范:0=OK, 1=WARNING, 2=CRITICAL, 3=UNKNOWN
- 输出必须包含状态文本:第一行输出状态描述
- 性能数据可选但推荐:用
| 分隔 - 处理超时:在合理时间内返回
- 输出到 stdout:Nagios 只读取 stdout
- 错误信息:有意义的错误描述
4.2 Shell 插件模板
#!/bin/bash
# check_custom.sh - 自定义检查插件模板
# 版本: 1.0
# 作者: DevOps Team
# 描述: 检查自定义指标
PROGNAME=$(basename $0)
PROGPATH=$(dirname $0)
VERSION="1.0"
# 退出码
OK=0
WARNING=1
CRITICAL=2
UNKNOWN=3
# 默认参数
HOST=""
METRIC=""
WARN=""
CRIT=""
# 使用帮助
print_usage() {
echo "Usage: $PROGNAME -H <host> -M <metric> -w <warning> -c <critical>"
echo " $PROGNAME -h"
}
print_help() {
print_usage
echo ""
echo "Check custom metric for a host."
echo ""
echo "Options:"
echo " -H Host name or IP address"
echo " -M Metric to check (cpu|memory|disk)"
echo " -w Warning threshold"
echo " -c Critical threshold"
echo " -h Print this help"
echo ""
echo "Examples:"
echo " $PROGNAME -H 192.168.1.1 -M cpu -w 80 -c 95"
echo " $PROGNAME -H 192.168.1.1 -M memory -w 80 -c 95"
}
# 参数解析
while getopts "H:M:w:c:h" opt; do
case $opt in
H) HOST=$OPTARG ;;
M) METRIC=$OPTARG ;;
w) WARN=$OPTARG ;;
c) CRIT=$OPTARG ;;
h) print_help; exit $UNKNOWN ;;
*) print_usage; exit $UNKNOWN ;;
esac
done
# 参数验证
if [ -z "$HOST" ] || [ -z "$METRIC" ] || [ -z "$WARN" ] || [ -z "$CRIT" ]; then
echo "UNKNOWN: Missing required parameters"
print_usage
exit $UNKNOWN
fi
# 获取指标值
case $METRIC in
cpu)
VALUE=$(check_cpu_usage $HOST)
UNIT="%"
;;
memory)
VALUE=$(check_memory_usage $HOST)
UNIT="%"
;;
disk)
VALUE=$(check_disk_usage $HOST)
UNIT="%"
;;
*)
echo "UNKNOWN: Unknown metric '$METRIC'"
exit $UNKNOWN
;;
esac
# 检查指标是否获取成功
if [ -z "$VALUE" ]; then
echo "UNKNOWN: Unable to get $METRIC value for $HOST"
exit $UNKNOWN
fi
# 阈值判断
PERFDATA="$METRIC=${VALUE}${UNIT};${WARN};${CRIT}"
if [ $(echo "$VALUE > $CRIT" | bc -l) -eq 1 ]; then
echo "CRITICAL: $METRIC=${VALUE}${UNIT} (threshold=${CRIT}${UNIT}) | $PERFDATA"
exit $CRITICAL
elif [ $(echo "$VALUE > $WARN" | bc -l) -eq 1 ]; then
echo "WARNING: $METRIC=${VALUE}${UNIT} (threshold=${WARN}${UNIT}) | $PERFDATA"
exit $WARNING
else
echo "OK: $METRIC=${VALUE}${UNIT} | $PERFDATA"
exit $OK
fi
4.3 Python 插件模板
#!/usr/bin/env python3
# check_custom.py - Python 自定义插件模板
import sys
import argparse
from enum import IntEnum
class State(IntEnum):
OK = 0
WARNING = 1
CRITICAL = 2
UNKNOWN = 3
class NagiosPlugin:
def __init__(self, name, version, description):
self.name = name
self.version = version
self.description = description
self.args = None
self.perfdata = []
self.messages = {State.OK: [], State.WARNING: [], State.CRITICAL: [], State.UNKNOWN: []}
def add_args(self):
parser = argparse.ArgumentParser(description=self.description)
parser.add_argument('-H', '--host', required=True, help='Host address')
parser.add_argument('-w', '--warning', type=float, help='Warning threshold')
parser.add_argument('-c', '--critical', type=float, help='Critical threshold')
parser.add_argument('-t', '--timeout', type=int, default=30, help='Timeout in seconds')
parser.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
return parser
def add_perfdata(self, label, value, uom='', warn='', crit='', min_val='', max_val=''):
perf = f"{label}={value}{uom};{warn};{crit};{min_val};{max_val}"
self.perfdata.append(perf)
def add_message(self, state, message):
self.messages[state].append(message)
def check(self):
"""Override this method with actual check logic"""
raise NotImplementedError
def exit(self, state):
all_messages = self.messages[state]
if not all_messages:
all_messages = self.messages[State.UNKNOWN]
output = f"{state.name}: {'; '.join(all_messages)}"
if self.perfdata:
output += f" | {' '.join(self.perfdata)}"
print(output)
sys.exit(state)
def run(self):
parser = self.add_args()
self.args = parser.parse_args()
try:
self.check()
except Exception as e:
print(f"UNKNOWN: {e}")
sys.exit(State.UNKNOWN)
# 使用示例
class CheckHTTP(NagiosPlugin):
def __init__(self):
super().__init__("check_http_custom", "1.0", "Custom HTTP check")
def check(self):
import requests
import time
try:
start = time.time()
response = requests.get(
f"http://{self.args.host}",
timeout=self.args.timeout
)
elapsed = time.time() - start
except requests.exceptions.Timeout:
self.add_message(State.CRITICAL, f"Connection timeout after {self.args.timeout}s")
self.exit(State.CRITICAL)
except Exception as e:
self.add_message(State.CRITICAL, f"Connection failed: {e}")
self.exit(State.CRITICAL)
self.add_perfdata("time", f"{elapsed:.3f}", "s",
self.args.warning or '', self.args.critical or '', "0")
if response.status_code >= 500:
self.add_message(State.CRITICAL, f"HTTP {response.status_code}")
self.exit(State.CRITICAL)
elif response.status_code >= 400:
self.add_message(State.WARNING, f"HTTP {response.status_code}")
self.exit(State.WARNING)
if self.args.critical and elapsed >= self.args.critical:
self.add_message(State.CRITICAL, f"Response time = {elapsed:.3f}s")
self.exit(State.CRITICAL)
elif self.args.warning and elapsed >= self.args.warning:
self.add_message(State.WARNING, f"Response time = {elapsed:.3f}s")
self.exit(State.WARNING)
self.add_message(State.OK, f"HTTP {response.status_code}, Response time = {elapsed:.3f}s")
self.exit(State.OK)
if __name__ == '__main__':
plugin = CheckHTTP()
plugin.run()
五、检查类型分类
5.1 按检查方式分类
| 检查方式 | 说明 | 适用场景 | 示例插件 |
|---|
| 主动检查 | Nagios 发起 | 本地和远程检查 | check_http, check_ping |
| 被动检查 | 外部提交 | 无法主动访问的系统 | NSCA, check_mk |
| SNMP 检查 | SNMP 协议 | 网络设备 | check_snmp |
| NRPE 检查 | NRPE 协议 | 远程 Linux 主机 | check_nrpe |
| SSH 检查 | SSH 协议 | 远程命令执行 | check_ssh |
| WMI 检查 | WMI 协议 | Windows 主机 | check_wmi_plus |
5.2 按监控对象分类
| 监控对象 | 推荐插件 | 说明 |
|---|
| Linux 系统 | check_nrpe + 插件 | 远程执行系统检查 |
| Windows 系统 | NSClient++ / check_wmi | 通过 WMI 或 NRPE |
| 网络设备 | check_snmp | SNMP 协议检查 |
| Web 应用 | check_http | HTTP/HTTPS 检查 |
| 数据库 | check_mysql, check_pgsql | 专用数据库插件 |
| 存储 | check_snmp + 厂商插件 | SNMP 或厂商 API |
| 虚拟化 | check_esx, check_vmware | VMware 插件 |
| 容器 | check_docker, check_k8s | Docker/K8s API |
六、插件测试
6.1 命令行测试
# 直接执行插件测试
/usr/local/nagios/libexec/check_ping -H 192.168.1.1 -w 100,20% -c 500,60%
# 查看退出码
echo $?
# 查看输出
/usr/local/nagios/libexec/check_http -H www.example.com -w 5 -c 10
# 详细输出模式(部分插件支持)
/usr/local/nagios/libexec/check_disk -v -w 20% -c 10% -p /
6.2 调试技巧
# 使用 strace 跟踪插件系统调用
strace -f /usr/local/nagios/libexec/check_http -H www.example.com
# 使用 timeout 测试超时处理
timeout 5 /usr/local/nagios/libexec/check_http -H slow-server.example.com
# 检查插件依赖
ldd /usr/local/nagios/libexec/check_http
# 测试 NRPE 远程插件
/usr/local/nagios/libexec/check_nrpe -H remote-host -c check_disk -a '-w 20% -c 10% -p /'
七、Nagios XI 与插件
Nagios XI(商业版本)对插件有额外支持:
| 功能 | Nagios Core | Nagios XI |
|---|
| 插件配置向导 | 无 | 内置向导 |
| 配置界面 | 命令行 | Web 界面 |
| 插件版本管理 | 手动 | 内置更新 |
| 性能图表 | 需插件 | 内置图表 |
| 插件市场 | Nagios Exchange | Nagios Exchange + XI 专属 |
八、注意事项
| 注意事项 | 说明 |
|---|
| 插件权限 | 确保插件有执行权限 |
| 依赖检查 | 编译插件前检查依赖库 |
| 超时设置 | 设置合理的插件超时 |
| 安全审计 | 社区插件使用前检查代码 |
| 版本兼容 | 注意插件与 Nagios 版本兼容性 |
| 资源消耗 | 避免过于频繁地执行耗资源的插件 |
九、本章小结
- Nagios 插件是独立的可执行程序,通过退出码和输出与核心通信
- 官方插件覆盖基础监控需求
- 社区插件(Nagios Exchange)提供丰富的扩展功能
- 自定义插件可以使用任何编程语言开发
- 插件测试应在命令行验证后再配置到 Nagios
下一章:第9章:NRPE 远程监控 - 学习如何使用 NRPE 监控远程主机。