强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Nagios 监控运维完整教程 / 第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 插件开发规范

  1. 必须遵循退出码规范:0=OK, 1=WARNING, 2=CRITICAL, 3=UNKNOWN
  2. 输出必须包含状态文本:第一行输出状态描述
  3. 性能数据可选但推荐:用 | 分隔
  4. 处理超时:在合理时间内返回
  5. 输出到 stdout:Nagios 只读取 stdout
  6. 错误信息:有意义的错误描述

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 版本兼容性
资源消耗 避免过于频繁地执行耗资源的插件

九、本章小结

  1. Nagios 插件是独立的可执行程序,通过退出码和输出与核心通信
  2. 官方插件覆盖基础监控需求
  3. 社区插件(Nagios Exchange)提供丰富的扩展功能
  4. 自定义插件可以使用任何编程语言开发
  5. 插件测试应在命令行验证后再配置到 Nagios

下一章第9章:NRPE 远程监控 - 学习如何使用 NRPE 监控远程主机。