第九章:通知系统
欢迎回到Nagios Core!
到目前为止,我们已经了解了Nagios如何加载配置(第四章:配置加载)以确定监控对象(第三章:对象定义),如何调度监控任务(第五章:事件调度),如何执行检查(通常使用工作者进程实现检查执行),以及如何处理结果来更新状态和检测问题或恢复(第八章:检查结果处理)。
现在假设Nagios检测到"Web服务器1: HTTP"服务出现问题,仅仅发现问题是不够的。我们作为管理员需要被告知
!
这就是通知系统的核心作用。
什么是通知?
通知是Nagios Core向相关人员(管理员、支持团队等)报告基础设施监控事件的重要机制。当主机或服务进入问题状态(如DOWN、CRITICAL或WARNING)或恢复健康状态(UP或OK)时,通知系统负责向正确联系人发送警报。
这就像是应急响应系统:监控引擎发现火情("Web服务器1: HTTP处于CRITICAL状态!"),通知系统则负责拨打指定电话、发送邮件或触发传呼设备通知相关人员。
通知系统具备智能判断能力,通过配置可确定:
- 通知对象(特定联系人或组)
- 通知时机(特定时间段)
- 通知方式(邮件、短信、自定义脚本)
- 触发状态(例如仅对CRITICAL状态告警)
- 问题确认状态(避免重复通知已处理问题)
- 计划维护时段(抑制维护期间的告警)
- 升级规则(问题持续时通知不同人员)
- 依赖关系(当父节点不可达时不触发子节点告警)
这种机制确保告警的精准性、及时性和相关性,避免告警疲劳。
典型案例:"Web服务器1: HTTP"故障处理
当"Web服务器1: HTTP"服务连续失败检查达到max_check_attempts
阈值,检查结果处理系统会将其状态更新为HARD CRITICAL,触发通知流程:
- 识别HARD CRITICAL状态变化
- 查询服务配置获取关联联系人组(示例中为
admins
组) - 验证全局和服务级通知启用状态
- 检查维护时段/确认状态(若存在则终止流程)
- 验证通知时间段有效性(示例为
24x7
) - 检查依赖关系(如父路由是否宕机)
- 确认CRITICAL状态是否配置告警
- 计算当前通知次数(首次为1,后续递增)
- 根据升级规则确定最终通知列表
- 为每个联系人构建通知命令(使用
$HOSTNAME$
等宏变量) - 通过工作者进程执行通知命令
- 更新服务状态数据(最后通知时间/计数器)
核心概念
- 联系人与联系组:定义通知接收者及其属性(联系方式、时段等)
- 通知命令 :通过
command
对象定义的外部程序/脚本 - 通知选项 :
notification_options
指定触发状态(如w,u,c,r
) - 通知时段:使用Timeperiod对象限制通知时间
- 依赖关系:通过执行依赖和通知依赖实现级联抑制
- 升级规则 :
hostescalation
/serviceescalation
定义通知升级策略 - 维护时段:计划性维护期间抑制通知
- 确认标记:通过CGI界面标记已处理问题
- 通知间隔:定义重复通知的最小时间间隔
底层工作机制
通知流程由检查结果处理系统触发,主要代码逻辑位于base/notifications.c
,关键流程包括:

核心函数service_notification
处理服务通知流程,通过多层验证确保符合配置规则。
关键验证函数check_service_notification_viability
包含28项检查条件,涵盖状态类型、确认标记、依赖关系等验证。
代码解析
通知系统主要代码结构:
c
// 服务通知主函数(简化版)
int service_notification(service *svc, int type, ...) {
/* 验证通知可行性 */
if(check_service_notification_viability(...) == ERROR) return;
/* 创建通知列表 */
create_notification_list_from_service(...);
/* 处理宏变量 */
grab_host_macros_r(...);
grab_service_macros_r(...);
/* 遍历通知列表 */
for(temp_notification = notification_list; ...) {
/* 执行通知命令 */
notify_contact_of_service(...);
}
/* 更新状态数据 */
update_service_status(...);
}
通知命令执行函数notify_contact_of_service
通过工作者进程实现异步执行:
c
int notify_contact_of_service(...) {
/* 获取通知命令 */
get_raw_command_line_r(...);
/* 宏扩展处理 */
process_macros_r(...);
/* 工作者进程执行 */
wproc_notify(...);
}
实现价值
当"Web服务器1: HTTP"发生故障时,通知系统通过多层验证确保:
- 仅当
HARD状态
且未确认
时触发 - 在指定时段通知
正确联系人组
- 自动过滤依赖故障的冗余告警
- 支持多种通知方式
扩展
- 通过宏变量动态生成告警内容
- 工作者进程实现高并发通知
通过宏变量动态生成告警内容
宏变量(如$HOSTNAME$
、$SERVICESTATE$
)是预定义的占位符,在告警触发时会被实时替换为具体的监控对象信息。
调用grab_host_macros_r()
和grab_service_macros_r()
函数会自动提取当前主机/服务的状态数据,填充到告警模板中生成最终通知内容。例如:
css
"警报:$HOSTNAME$的$SERVICEDESC$状态为$SERVICESTATE$"
实际发送时会变成:
css
"警报:web-server01的CPU负载状态为CRITICAL"
总结
通知系统是Nagios Core的核心通信层,通过联系人、时段、依赖关系等多维度配置实现精准告警路由。结合宏变量系统和工作者进程
,确保基础设施状态变化及时准确地传达给运维团队。
第十章:事件代理(NEB)将解析外部程序与Nagios Core的深度集成机制。
第十章:事件代理(NEB)
欢迎来到Nagios Core的最终章~
我们已经涵盖了大量内容:如何通过CGI界面
查看Nagios状态,状态数据的来源
(状态数据管理),Nagios如何知道要监控什么
(对象定义和配置加载),如何决定检查时机
(事件调度),如何实际执行检查
(检查执行,通常使用工作者),如何分析结果
(检查结果处理),以及发现问题时如何发出警报
(通知)。
所有这些组件都在Nagios Core主引擎中协同工作。
但如果我们需要另一个应用程序------可能是自定义仪表板、将数据发送到数据库的日志系统,或自动修复工具------需要实时了解Nagios内部发生的所有细节,甚至需要告诉Nagios执行某些操作时,该怎么办?
作为主要用
C语言编写的单进程程序
,Nagios Core如何共享其内部事件并允许其他程序深度交互?
这正是事件代理 (Event Broker),通常称为NEB(Nagios Event Broker)发挥作用的地方。
什么是事件代理(NEB)?
将Nagios Core引擎视为监控系统的心脏。它持续执行检查、处理结果、检测状态变化并决定通知。
事件代理 就像直接连接这个心脏的动脉和静脉网络,实时反馈
几乎所有的内部活动,在某些情况下允许外部系统回传指令
。
这是为开发者设计的底层接口
,用于构建需要深度访问Nagios Core内部机制的插件、扩展或集成方案。
事件代理的核心功能:
- 实时数据流:外部模块(插件)可注册接收特定事件的实时通知(如"服务检查完成"、"主机状态变化"、"通知已发送"、"维护时段开始")
- 结构化数据:事件发生时,不仅发送简单消息,还提供结构化数据(包含主机名、服务描述、当前状态、插件输出、时间信息等)
- 自适应控制:特定类型的模块可在Nagios执行操作前/后被调用,允许修改数据或向引擎注入指令
本质上,NEB是Nagios Core引擎本身的插件API 。不同于为Nagios执行检查的普通插件,NEB模块是与Nagios深度集成
的插件。
应用场景:将服务检查结果记录到数据库
假设我们需要构建一个系统,将每次服务检查结果(包含主机、服务、状态、输出、时间和性能数据)记录到时序数据库,用于长期分析和自定义图表
,这需要超越标准status.dat
或日志文件的功能。
没有NEB
时,实现非常困难。可能需要解析人类可读的日志文件,或截取插件输出(不稳定且复杂)。
使用NEB可创建自定义模块:
- 告知Nagios Core:"需要接收每次服务检查完成的通知"
- 提供特定回调函数
- 在回调中接收结构化数据包(包含检查细节)
- 将数据写入数据库
这是从Nagios Core引擎直接获取所需数据的简洁、高效、可靠方式。
⭕核心:模块、回调、事件
NEB系统围绕以下核心概念构建:
- NEB模块(
broker_module
) :Linux平台为.so
的共享库,通过nagios.cfg
的broker_module
指令加载。每个模块需包含初始化(_module_init
)和终止(_module_deinit
)函数 - 事件 :Nagios运行过程中的特定时刻或操作(如
NEBCALLBACK_SERVICE_CHECK_DATA
服务检查完成、NEBCALLBACK_STATE_CHANGE_DATA
状态变化等),涵盖Nagios生命周期的各个方面 - 回调 :模块内定义的函数,注册到NEB系统并指定关联事件类型。事件发生时,Nagios调用回调函数并传递相关数据结构
- 注册 :模块初始化时通过
neb_register_callback
注册回调,类似电视频道订阅机制
底层运行机制
Nagios Core启动时加载配置后,读取broker_module
指令加载模块:

Nagios主循环执行任务时,在关键节点收集信息到标准数据结构(定义于include/nebstructs.h
),然后调用NEB系统:

broker_service_check
等函数(位于base/broker.c
)在事件发生时被调用,将数据打包至nebstruct_*
结构体,通过neb_make_callbacks
分发回调。
代码实现
主要接口定义于:
include/nebcallbacks.h
:回调类型定义include/nebmods.h
:模块管理include/nebstructs.h
:数据结构
模块启用配置示例:
cfg
# nagios.cfg配置
# 加载NDOUtils模块记录数据到数据库
broker_module=/usr/local/nagios/bin/ndomod.so config_file="/usr/local/nagios/etc/ndomod.cfg"
回调注册示例:
c
// 模块初始化函数内注册
int neb_register_callback(NEBCALLBACK_SERVICE_CHECK_DATA, module_handle, 0, my_service_check_handler);
服务检查数据结构:
c
typedef struct nebstruct_service_check_struct {
int type; // 事件子类型
char *host_name; // 主机名
char *service_description; // 服务名
struct timeval start_time; // 检查开始时间
char *output; // 插件输出
char *perf_data; // 性能数据
// ...其他字段
} nebstruct_service_check_data;
场景实现方案
编写NEB模块注册NEBCALLBACK_SERVICE_CHECK_DATA
事件回调,接收nebstruct_service_check_data
结构体后,将结构化数据直接写入
数据库。
这种方法比
解析日志
更高效可靠。
总结
Nagios事件代理(NEB)通过回调机制提供实时事件流和自适应控制,使开发者能创建深度集成的扩展功能,极大增强了Nagios Core的灵活性和可扩展性。
这是构建高级监控解决方案和定制化数据处理系统的关键技术。
END ★,° :.☆( ̄▽ ̄).°★ 。