第三章:监控对象定义
欢迎回来!
在上一章状态数据管理中,我们探索了Nagios如何跟踪监控对象的实时状态——例如"Web Server 1"是否在线、最近检测时间等。
但在Nagios能够感知状态信息之前,它需要先明确监控对象的存在及其监控方式。这正是监控对象定义的核心作用。
对象定义解析
核心概念
对象定义如同Nagios的工程蓝图,定义了以下要素:
- 监控实体清单:服务器、网络设备、服务组件等
- 检测策略:检测频率、重试机制、告警阈值
- 关联关系:设备依赖链、通知策略、故障升级路径
对象类型体系
Nagios通过11种核心对象类型构建监控拓扑:
对象类型 | 功能描述 | 示例配置项 |
---|---|---|
主机(Host ) |
物理/虚拟设备实体 | 网络服务器、路由器 |
服务(Service ) |
主机承载的具体检测项 | HTTP服务、磁盘空间 |
指令(Command ) |
检测动作的执行方式(通常调用插件脚本) | check_http、notify_sms |
时段(Timeperiod ) |
定义检测/通知的时间窗口 | 工作日9-18点、7x24小时 |
联系人(Contact ) |
告警接收者信息 | 运维值班员、NOC团队 |
联系组(Contactgroup ) |
联系人分组管理 | admins、emergency_team |
主机组(Hostgroup ) |
逻辑主机集群 | web_cluster、db_nodes |
服务组(Servicegroup ) |
服务集合管理 | critical_checks、network_services |
依赖(Dependency ) |
定义对象间检测依赖关系 | 数据库服务依赖存储阵列 |
升级(Escalation ) |
告警升级策略 | 30分钟未恢复通知主管 |
模板(Template ) |
通用配置模板(通过use 指令继承) |
generic-host、linux-server |
拓扑:研究几何图形在连续变形(如拉伸、弯曲)下不变性质
的数学分支,比如洞的数量。
配置文件
文件结构示例
# 主机定义示例(hosts.cfg)
define host {
use linux-server ; 继承Linux服务器模板
host_name Web_Server_01 ; 设备标识
alias 主Web节点 ; 中文描述
address 192.168.1.100 ; IP地址
check_command check-host-alive ; 存活检测指令
max_check_attempts 5 ; 最大重试次数
check_interval 300 ; 5分钟检测间隔
contact_groups infra-team ; 联系组
}
# 服务定义示例(services.cfg)
define service {
use generic-service ; 基础服务模板
host_name Web_Server_01
service_description HTTP_Status ; 服务描述
check_command check_http!80 ; 带端口参数的检测指令
check_interval 60 ; 1分钟检测频率
notification_options w,u,c ; 警告/未知/严重状态触发通知
}
模板继承机制
classDiagram
class generic-host {
+check_interval 60
+max_check_attempts 3
+notification_interval 120
}
class linux-server {
+check_command check_ssh
+notification_period 24x7
}
class Web_Server_01 {
+address 192.168.1.100
+contact_groups infra-team
}
generic-host <|-- linux-server
linux-server <|-- Web_Server_01
代码实现
内存数据结构
// include/objects.h 精简版结构体
typedef struct host {
char *name; // 主机名
char *address; // IP地址
int check_interval; // 检测间隔
struct service *services; // 关联服务链表
struct host *next; // 主机链表指针
} host;
typedef struct service {
char *description; // 服务描述
char *check_command; // 检测指令
struct host *host; // 隶属主机
struct service *next; // 服务链表指针
} service;
配置加载流程
// objects.c 配置加载伪代码
void load_objects() {
read_main_config(); // 解析nagios.cfg
parse_host_definitions(); // 加载hosts.cfg
parse_service_definitions(); // 加载services.cfg
resolve_dependencies(); // 解析对象关联
build_hashtables(); // 构建哈希索引
}
高级特性
动态对象注入
通过外部命令接口实现运行时对象更新:
# 动态添加主机
echo "[$(date +%s)] ADD_HOST;New_Server;192.168.2.10;generic-host" > cmd_file
# 动态更新检测间隔
echo "[$(date +%s)] CHANGE_HOST_CHECK_INTERVAL;Web_Server_01;300" > cmd_file
对象验证工具
使用nagios -v
命令进行预检:
nagios -v /usr/local/nagios/etc/nagios.cfg
# 输出包含:
# 总对象数:238
# 错误:未找到'check_http'指令定义
# 警告:主机组'db_nodes'为空
最佳实践
配置优化建议
模块化分割
按功能拆分为hosts/
,services/
,commands/
等目录版本控制
使用Git管理配置变更,结合CI/CD流水线模板分层
构建基础模板->操作系统模板->业务模板三级体系自动生成
通过CMDB系统自动生成主机/服务定义文档嵌入
在配置中使用标准化注释:/* 电商核心数据库节点 * 责任人:DBA团队 * 维护窗口:每周四 02:00-03:00 */ define host { ... }
总结
监控对象定义体系通过:
- 声明式配置:文本化定义监控拓扑
- 继承复用:模板机制减少重复配置
- 动态关联:运行时内存结构互连
==构建起Nagios监控体系的基石。==下一章将深入解析配置加载机制,揭示Nagios如何高效载入并验证这些配置。
第四章:配置加载
在上一章第三章:对象定义中,我们了解到Nagios需要蓝图——即对象定义——来知晓监控环境中存在哪些主机、服务和其他资源。
我们看到这些定义如何以纯文本.cfg
文件的形式编写。
但运行中的Nagios Core引擎究竟如何实际读取、理解和使用这些定义?这就是配置加载的用武之地。
什么是配置加载?
配置加载是Nagios Core引擎读取其操作手册的过程。
这个手册由所有设置好的配置文件组成。就像启动复杂机器时,我们首先要输入所有设置参数和操作指令。
具体来说,配置加载处理:
- 读取配置文件:打开并读取主配置文件(
nagios.cfg
)以及nagios.cfg
指向的所有对象定义文件(.cfg
)。 - 解析:解释这些文件中的文本,理解结构(
define type { ... }
)和指令(key=value
)。 - 构建内存模型:在Nagios引擎内存中创建C数据结构,以引擎可快速处理的方式表示配置(主机、服务、命令等)。
- 对象链接:连接相关部分(例如查找"Web Server 1"的
struct host
,并将其HTTP服务的struct service
链接到该主机)。 - 验证:检查错误、不一致和逻辑问题(例如为不存在的主机定义服务,或创建循环依赖)。
这个过程发生在Nagios Core引擎首次启动时,以及每次通知其重新加载配置后(通常在修改
.cfg
文件后)。
应用案例:让Nagios监控"Web Server 1"
以我们持续使用的"Web Server 1"为例。
我们已在.cfg
文件中定义该主机及其服务(如HTTP和Ping)(如第三章:对象定义所示)。要使Nagios实际开始检查"Web Server 1",配置加载过程必须成功读取并处理这些定义。
如果配置文件中存在错误——可能在服务定义中将"Web Server 1"拼写错误,或定义了不存在的命令——配置加载过程将检测到此错误,Nagios会拒绝启动或重新加载,并告知问题所在。
幕后工作原理
以下是Nagios Core引擎在配置加载期间执行步骤的简化说明:
- 读取主配置(nagios.cfg):Nagios首先读取主配置文件。该文件包含全局程序设置,并关键性地告知Nagios其他配置文件的存储位置(使用
cfg_file
或cfg_dir
指令)。 - 读取对象配置(.cfg):基于
nagios.cfg
中的路径,Nagios打开并读取所有对象定义文件。 - 初始解析与模板化:解析文件并创建临时内存结构(如
xodtemplate_host
、xodtemplate_service
——这些处理模板继承)。若使用模板(use指令
),Nagios会扩展这些模板以创建每个对象的完整定义。 - 构建最终结构:临时结构被转换为引擎使用的最终就绪内存对象结构(
struct host
、struct service
等)。 - 链接与解析:解析如
host_name
、check_command
、contact_groups
等指令。这意味着Nagios会找到被引用对象的实际内存结构(例如找到"Web Server 1"的struct host
并在服务结构中存储指向它的指针)。此步骤对Nagios快速导航配置至关重要。 - 验证:Nagios执行系列检查确保配置逻辑完整。包括检查所有被引用对象是否存在、验证关系(如父/子主机)、查找循环依赖。
- 成功或失败:若验证通过,配置被加载,Nagios准备就绪。若验证失败,Nagios记录详细错误信息并退出或中止重载,防止以错误配置运行。
代码解析
配置加载逻辑分布在多个文件中
base/config.c
文件包含读取主配置和执行验证检查的核心功能。解析和模板化逻辑由
xdata/xodtemplate.c
等文件处理。
查看部分代码片段:
base/config.c
中的read_main_config_file
函数负责打开nagios.cfg
并读取其指令。
// 摘自base/config.c(简化版)
int read_main_config_file(char *main_config_file) {
// ... 文件打开和初始化 ...
/* 处理配置文件中的所有行 */
while(1) {
// ... 读取一行(可能跨多行)...
// ... 去除空格和注释 ...
// ... 解析'variable=value'...
/* 处理变量/值 */
if(!strcmp(variable, "resource_file")) {
// 读取资源文件(用于$USERx$宏)
if(read_resource_file(...) == ERROR) { error = TRUE; break; }
} else if(!strcmp(variable, "log_file")) {
my_free(log_file);
log_file = nspath_absolute(value, config_file_dir);
} else if(!strcmp(variable, "command_file")) {
my_free(command_file);
command_file = nspath_absolute(value, config_file_dir);
// ... 保存为宏 ...
} else if(!strcmp(variable, "status_file")) {
// 状态数据管理使用(第二章)
status_file = nspath_absolute(value, config_file_dir);
}
// ... 其他程序设置 ...
else if(strstr(input, "cfg_file=") == input || strstr(input, "cfg_dir=") == input) {
// 这些告知Nagios对象定义的存储位置
continue; // 由read_all_object_data后续处理
}
// ... 处理其他变量 ...
else {
// 未知变量
error = TRUE; break;
}
}
// ... 处理错误,关闭文件 ...
return OK; // 或ERROR
}
该函数读取nagios.cfg
,为程序设置全局变量(如log_file
、command_file
),并识别包含对象定义的文件/目录(cfg_file
、cfg_dir
)。此时尚未处理对象定义本身,但已记录其位置。
读取nagios.cfg
后,引擎调用函数读取对象定义文件。read_all_object_data
是启动该过程的高级函数,最终调用read_object_config_data
(随后使用xdata/xodtemplate.c
中的模板化/解析逻辑)。
// 摘自base/config.c(简化版)
int read_all_object_data(char *main_config_file) {
int result = OK;
int options = READ_ALL_OBJECT_DATA; // 读取所有对象类型的标志
/* 从外部源读取所有配置数据 */
// 此函数(定义在其他地方,使用xodtemplate逻辑)
// 读取cfg_file/cfg_dir指定的文件,解析定义,
// 处理模板,构建内存结构。
result = read_object_config_data(main_config_file, options);
if(result != OK) return ERROR;
return OK;
}
read_object_config_data
的细节和模板化/解析由xodtemplate
函数处理(使用xdata/xodtemplate.h
中的结构如xodtemplate_host
、xodtemplate_service
,并将其转换为include/objects.h
中的struct host
、struct service
),此处不深入探讨。
关键是此步骤使用第三章:对象定义中见过的对象结构,将解析后的配置载入Nagios内存。
所有文件读取解析后,Nagios执行验证检查。base/config.c
中的pre_flight_check
函数组织这些检查。
// 摘自base/config.c(简化版)
int pre_flight_check(void) {
int warnings = 0;
int errors = 0;
if(verify_config)
printf("正在检查配置...\n");
/********************************************/
/* 检查对象关系 */
/********************************************/
// 检查被引用对象是否存在(如服务的host)
pre_flight_object_check(&warnings, &errors);
/********************************************/
/* 检查主机间的循环路径 */
/********************************************/
// 检查父/子主机关系和依赖中的循环
pre_flight_circular_check(&warnings, &errors);
/********************************************/
/* 检查全局事件处理命令... */
/********************************************/
// 确保配置的命令存在
if(global_host_event_handler != NULL) {
global_host_event_handler_ptr = find_bang_command(global_host_event_handler);
if (global_host_event_handler_ptr == NULL) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "错误:全局主机事件处理命令'%s'未定义!", global_host_event_handler);
errors++;
}
// ... 类似的服务处理程序检查 ...
}
// ... 其他多项检查 ...
if(verify_config) {
printf("\n总警告数:%d\n", warnings);
printf("总错误数:%d\n", errors);
}
return (errors > 0) ? ERROR : OK;
}
pre_flight_check
函数调用pre_flight_object_check
和pre_flight_circular_check
等专业函数执行详细验证。pre_flight_object_check
确保对象引用(如服务定义中的host_name
)实际存在于已加载配置中。
pre_flight_circular_check
使用图遍历算法(如深度优先搜索)检测父/子主机关系和执行/通知依赖中的循环,这些会导致Nagios出现问题。
若任何检查发现错误,pre_flight_check
返回ERROR
,Nagios将记录详细信息并停止。
如何解决我们的应用案例
通过成功完成配置加载过程,Nagios现已读取"Web Server 1"的定义、其HTTP和Ping服务、使用的命令(check_http
、check_ping
)、联系人(admins
)、时间段(24x7
)以及其他相关对象。
所有这些信息现在以互连的C结构形式有序存储在Nagios Core引擎内存中。Nagios现已具备监控环境的内部映射和监控规则,准备进入下一阶段:决定何时检查"Web Server 1"及其服务。
结论
配置加载是Nagios Core运行的关键第一步。
这是读取.cfg
文件提供的蓝图,将其转换为内部内存模型,链接所有部分,并验证逻辑合理性的过程。
成功的配置加载意味着Nagios理解需要监控的内容和方法,为其进入实际系统检查的活跃工作阶段做好准备。
现在Nagios知晓需要监控的内容
,下一步是决定何时执行这些检查
。