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

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_pingICMP Ping 检查-H host -w warn -c crit -p packets
check_tcpTCP 端口检查-H host -p port -t timeout
check_udpUDP 端口检查-H host -p port -s send -e expect
check_sshSSH 服务检查-H host -p port -t timeout
check_dnsDNS 解析检查-H hostname -s server
check_digDNS Dig 检查-H host -l lookup -T type
check_fping高效 Ping 检查-H host -w warn -c crit
check_smtpSMTP 服务检查-H host -p port -e expect
check_pop3POP3 服务检查-H host -p port -e expect
check_imapIMAP 服务检查-H host -p port -e expect
check_ntpNTP 时间检查-H host -w warn -c crit
check_ntp_peerNTP 对等检查-H host -w warn -c crit
check_ldapLDAP 服务检查-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综合检查套件Pythoncheck-mk.org
check_nrpeNRPE 客户端Cnagios.org
check_mysql_healthMySQL 深度检查Perllabs.consol.de
check_oracle_healthOracle 深度检查Perllabs.consol.de
check_mongodbMongoDB 检查Pythongithub
check_redisRedis 检查Pythongithub
check_elasticsearchElasticsearch 检查Pythongithub
check_dockerDocker 容器检查Shellgithub
check_ssl_certSSL 证书详细检查Shellgithub
check_puppetPuppet 状态检查Rubygithub
check_raidRAID 状态检查Perlgithub
check_iostatI/O 统计检查Shellgithub
check_mem内存使用检查Shellgithub
check_logfiles日志文件检查Perlconsol.de
check_multi多检查聚合Perlgithub
check_urlURL 内容检查Perlgithub

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_snmpSNMP 协议检查
Web 应用check_httpHTTP/HTTPS 检查
数据库check_mysql, check_pgsql专用数据库插件
存储check_snmp + 厂商插件SNMP 或厂商 API
虚拟化check_esx, check_vmwareVMware 插件
容器check_docker, check_k8sDocker/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 CoreNagios XI
插件配置向导内置向导
配置界面命令行Web 界面
插件版本管理手动内置更新
性能图表需插件内置图表
插件市场Nagios ExchangeNagios Exchange + XI 专属

八、注意事项

注意事项说明
插件权限确保插件有执行权限
依赖检查编译插件前检查依赖库
超时设置设置合理的插件超时
安全审计社区插件使用前检查代码
版本兼容注意插件与 Nagios 版本兼容性
资源消耗避免过于频繁地执行耗资源的插件

九、本章小结

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

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