[Nagios Core] 事件調度 | 檢查執行 | 插件與進程

第五章:事件調度

歡迎回到Nagios Core!

在上一章第四章:配置加載中,我們了解了Nagios如何讀取配置文件以知曉需要監控的對象,比如我們的朋友"Web Server 1"。此時Nagios內存中已構建完整的基礎設施拓撲圖。

僅僅知道存在什么是不夠的。Nagios需要主動執行操作,而且必須在正確的時間執行。何時檢查"Web Server 1"的可達性?何時檢查HTTP服務?何時保存當前狀態?

這就是事件調度的用武之地。

什么是事件調度?

將Nagios Core引擎視為擁有主日歷和鬧鐘的系統。事件調度就是管理這個日歷的機制,負責跟蹤所有未來需要執行的任務并在預定時間觸發它們。

本質上,Nagios是一個高度組織化的事件調度器。它維護著未來定時事件的隊列,這些事件代表著Nagios需要執行的所有操作

  • 對主機和服務執行主動檢查
  • 在問題發生或解決時發送通知
  • 執行狀態保存、日志輪轉等維護任務
  • 檢查被動檢查結果的"新鮮度"
  • 執行計劃停機開始/結束任務
  • 以及其他更多功能!

正是這種調度機制驅動著Nagios的所有活動。

用例:為"Web Server 1"調度檢查

基于前幾章加載的配置,Nagios已知曉"Web Server 1"及其HTTP和Ping服務,包括它們的check_interval(如每5分鐘檢查)和check_period(如24x7)。

事件調度組件利用這些信息向日歷添加事件:

  1. 立即(或啟動/重載后不久)計算"Web Server 1"及其服務的首次檢查時間
  2. 將"Web Server 1主機檢查"和"Web Server 1: HTTP服務檢查"、"Web Server 1: Ping服務檢查"事件加入隊列
  3. 當檢查事件到期時觸發執行
  4. 檢查運行并處理結果后(后續章節詳述),調度系統計算下次檢查時間(如5分鐘后)并新增檢查事件

這種調度、觸發和重新調度的持續循環確保按配置定期檢查所有對象。

核心概念:事件隊列與主循環

事件調度圍繞兩個核心理念構建:

  1. 事件隊列存儲所有未來事件的中心數據結構,按執行時間排序。Nagios使用高效優先隊列實現(內部稱squeue),專為快速事件添加和檢索優化
  2. 主執行循環:Nagios引擎持續運行的循環,每個周期中:
    • 查看隊列首部事件
    • 等待至事件到期
    • 取出事件并執行關聯任務
    • 循環事件計算下次執行時間并重新入隊

幕后工作機制

以下是Nagios完成配置加載后的核心調度流程:

在這里插入圖片描述

  1. 初始化(init_timing_loop):為所有配置對象計算初始next_check時間,創建timed_event對象入隊
  2. 主循環(event_execution_loop):進入無限循環
  3. 查看(peek):獲取隊列首部事件時間
  4. 等待/輪詢:使用iobroker_poll系統調用休眠至事件到期或外部輸入到達
  5. 取出處理(pop & handle):取出事件并通過handle_timed_event處理
  6. 事件特定邏輯:根據事件類型調用對應函數(如run_scheduled_service_check
  7. 重新調度:對循環事件計算下次執行時間并重新入隊
  8. 循環往復:持續處理后續事件

(FIFO)

代碼解析

核心調度邏輯位于base/events.c及相關頭文件:

// 簡化版timed_event結構(來自include/nagios.h)
typedef struct timed_event_struct {int     event_type;      // 事件類型time_t  run_time;        // Unix時間戳void    *event_data;     // 關聯數據指針int     recurring;       // 是否循環unsigned long event_interval; // 循環間隔// 其他字段...
} timed_event;// 全局事件隊列
extern squeue_t *nagios_squeue;

事件調度關鍵函數:

// 創建新事件并入隊(base/events.c簡化版)
timed_event *schedule_new_event(int event_type, ...) {timed_event *new_event = calloc(1, sizeof(timed_event));// 設置事件字段...add_event(nagios_squeue, new_event);return new_event;
}// 主事件循環(base/events.c簡化版)
int event_execution_loop(void) {while(1) {// 獲取下個事件時間temp_event = squeue_peek(nagios_squeue);// 計算等待時間poll_time_ms = ...;// 等待事件或外部輸入iobroker_poll(nagios_iobs, poll_time_ms);// 處理到期事件if (should_run_event(temp_event)) {handle_timed_event(temp_event);remove_event(nagios_squeue, temp_event);// 重新調度循環事件if(temp_event->recurring) reschedule_event(nagios_squeue, temp_event);}}
}// 事件處理器(base/events.c簡化版)
int handle_timed_event(timed_event *event) {switch(event->event_type) {case EVENT_SERVICE_CHECK:run_scheduled_service_check(...);break;// 其他事件類型處理...}
}

實現了一個事件調度系統的核心功能,用于管理和執行定時或周期性任務(如服務檢查)。

系統通過事件隊列管理待執行任務,主循環持續檢查while(1){}并執行到期事件

事件創建與入隊

schedule_new_event()函數負責創建新事件:

  • 使用calloc動態分配內存,創建timed_event結構體
  • 初始化事件類型等參數(代碼中...表示省略的細節)
  • 通過add_event()將事件插入優先級隊列nagios_squeue
  • 返回創建的事件指針,供后續操作使用

主事件循環

event_execution_loop()是持續運行的核心循環: while(1){}

  • squeue_peek()查看隊列中下一個即將觸發的事件(不取出)
  • 計算該事件的剩余等待時間poll_time_ms
  • iobroker_poll()同時監控外部輸入和等待事件到期
  • should_run_event()判斷事件是否到期,到期則調用handle_timed_event()執行
  • 執行后通過remove_event()移出隊列,若是周期性事件則用reschedule_event()重新入隊

事件處理邏輯

handle_timed_event()根據事件類型執行具體操作:

  • EVENT_SERVICE_CHECK類型觸發run_scheduled_service_check()
  • 其他事件類型通過類似switch-case分支處理
  • 實際系統中會包含更多事件類型(代碼中//其他事件類型處理...示意)

實現效果

通過事件調度系統,Nagios能夠:

  1. 將"Web Server 1"的配置轉換為可執行的定時事件
  2. 通過主循環持續監控和執行檢查
  3. 按配置間隔自動重新調度后續檢查
  4. 保持對所有監控資源的持續監測

主循環機制

  • 主循環機制是程序不斷重復執行的核心流程,用于處理輸入、更新狀態和輸出結果,直到滿足退出條件。

  • eg. int event_execution_loop(void) { while(1) {}}:無限循環查詢,通過break跳出

  • 例如游戲循環會持續檢測玩家操作、計算畫面變化并刷新顯示。

總結

事件調度是Nagios Core引擎的核心驅動力,通過精心設計的時間隊列管理和主循環機制,確保監控配置的主動實施。下一章我們將探討檢查執行的具體過程

第六章:檢查執行


第六章:檢查執行

在上一章第五章:事件調度中,我們了解到Nagios如何利用主日歷來決定事件發生的時間——包括何時需要檢查我們的朋友"Web Server 1"是否仍然可達或HTTP服務是否正常運作。

現在Nagios已經知道監控什么(對象定義),知道如何查找這些定義(配置加載),也知道*何時執行檢查*(事件調度)。

但它究竟如何執行檢查?如何發送ping請求或嘗試連接Web服務器?

這就是檢查執行系統的職責所在。

什么是檢查執行?

檢查執行系統是Nagios Core中負責實際執行已定義監控任務的核心組件。它就像行動執行者。當調度器發出"立即檢查Web Server 1的HTTP服務!"指令時,檢查執行系統接收命令并付諸實施。

關鍵在于,Nagios Core本身并不包含執行ping操作、檢查網頁或查看磁盤空間的代碼。

相反,它依賴于稱為插件外部程序(通常是小型腳本或可執行文件)。檢查執行系統的主要職責包括:

  1. 根據對象定義確定特定檢查所需的正確插件命令和參數
  2. 運行這個外部插件程序
  3. 捕獲插件執行結果

我們可以將其理解為:

Nagios將特定工具(插件)交給臨時工作進程,并指示"去檢查這個目標并反饋結果!"

用例分析:檢查"Web Server 1: HTTP"

讓我們追蹤當事件調度系統觸發"Web Server 1"HTTP服務檢查時發生的事件鏈:

  1. 調度器觸發"Web Server 1: HTTP"服務檢查的事件處理器
  2. 處理器查找該服務的配置信息(來自已加載的對象定義)。找到我們在第三章:對象定義中定義的check_command指令,即check_http。完整命令行可能類似/usr/local/nagios/libexec/check_http -H 192.168.1.100
  3. 檢查執行系統準備執行該命令
  4. 在運行Nagios Core的系統上啟動/usr/local/nagios/libexec/check_http作為獨立進程
  5. 系統等待check_http插件完成
  6. 插件運行時,檢查執行系統捕獲其標準輸出(如"HTTP OK: HTTP/1.1 200 OK - 154 bytes in 0.052 second performance data…")和標準錯誤(如果有)
  7. 插件退出時,檢查執行系統捕獲退出代碼。該代碼遵循Nagios插件標準:
    • 0: 正常
    • 1: 警告
    • 2: 嚴重
    • 3: 未知
  8. 收集的輸出、標準錯誤和退出代碼組合成"檢查結果"
  9. 該結果傳回Nagios主引擎進行下一階段處理:檢查結果處理

這個循環過程會為調度引擎安排的所有活動主機和服務檢查重復執行。

?核心:插件與進程執行

檢查執行系統的核心思想包括:

  • 插件:實際執行監控的工作單元。它們是獨立的程序BashPythonPerl腳本或編譯二進制文件),接收參數(如主機IP、端口號、閾值)并執行特定檢查。其輸出和退出代碼是向Nagios反饋的標準方式。Nagios Core自帶標準插件集(nagios-plugins),但支持用戶自定義開發
  • 外部進程執行:出于安全性和穩定性考慮,Nagios從不在主進程內部運行插件。而是通過系統調用將每個插件作為獨立子進程啟動。這意味著即使插件崩潰或掛起,也不會影響整個Nagios引擎
  • 命令構造:Nagios從配置中獲取check_command和定義參數(如第三章:對象定義中check_ping!100,20%!500,60%),擴展任何宏(如$HOSTNAME$$SERVICESTATE$),構建最終執行的命令行字符串
  • 結果捕獲:Nagios需要通過管道連接插件的標準輸出和標準錯誤流來讀取打印內容,同時使用系統調用(waitpid)獲取插件退出狀態(linux下一切皆文件【Linux】重定向 | 為什么說”一切皆文件?“)

頻繁運行大量外部進程可能消耗系統資源。–池化解決

Nagios Core采用專用系統高效管理這些插件執行,通常通過準備就緒的工作進程池(Workers)來啟動檢查。

?幕后工作原理

當事件處理器決定運行檢查時(如第五章:事件調度中提到的handle_timed_event函數,特別是調用run_scheduled_service_checkrun_scheduled_host_check的部分),檢查執行的簡化流程如下:

在這里插入圖片描述

  1. 事件(如計劃檢查或按需檢查)通知主引擎需要執行特定主機/服務檢查
  2. 引擎查找相關對象定義及其關聯的check_command
  3. 準備需要執行的完整命令行字符串,包括擴展宏
  4. 主引擎不直接執行命令,而是通過消息或請求將任務分派給工作進程(如base/nagios.cinclude/workers.h代碼片段所示,詳細內容將在下一章討論)。該請求包含命令行檢查超時被檢主機/服務信息
  5. 工作進程接收任務請求
  6. 工作進程使用底層系統調用(forkexecpipewaitpid啟動指定插件命令作為自身子進程。建立管道捕獲插件的標準輸出和標準錯誤
  7. 插件程序運行,執行檢查(如連接目標主機/端口),向標準輸出打印結果,并以適當狀態碼退出
  8. 工作進程讀取插件寫入標準輸出和標準錯誤管道的內容。同時等待插件進程結束并獲取退出狀態
  9. 工作進程將收集的輸出、標準錯誤、退出狀態和計時信息打包成結構化結果
  10. 工作進程通過進程間通信通道(如套接字)將結構化檢查結果返回主引擎
  11. 主引擎接收結果并傳遞給檢查結果處理系統更新狀態、記錄事件并可能發送通知

這種架構(特別是工作進程機制)使Nagios能夠(多進程)并發運行成百上千次檢查,同時保持主調度和事件處理循環的持續運行

代碼

Nagios Core的實際底層進程執行邏輯主要依賴runcmd庫(lib/runcmd.hlib/runcmd.c),該庫提供安全執行外部命令并捕獲輸出和退出狀態的方法

但在標準Nagios Core設置中,主引擎不直接調用runcmd執行檢查,而是通過工作進程系統在內部使用runcmd

查看主引擎用于向工作進程請求檢查執行任務的接口(定義于include/workers.h):

// 摘自 include/workers.h(簡化版)// 保存工作進程執行任務后返回結果的結構體
typedef struct wproc_result {unsigned int job_id;unsigned int type;       // 任務類型(WPJOB_CHECK、WPJOB_NOTIFY等)char *command;           // 實際執行的命令行char *outstd;            // 命令的標準輸出char *outerr;            // 命令的標準錯誤int wait_status;         // waitpid的原始狀態(包含退出碼)int exited_ok;           // 進程是否正常退出int early_timeout;       // 是否提前超時// ... 其他時間和狀態字段 ...
} wproc_result;// 主引擎請求工作進程執行檢查任務的函數
// 注意:這是主引擎概念上的簡化函數調用
// 實際接口使用消息隊列或套接字
// 摘自 include/workers.h(概念簡化版)
extern int wproc_run_check(check_result *cr, char *cmd, nagios_macros *mac);
// 該函數向工作進程發送執行'cmd'命令的請求
// 'cr'是用于存儲結果指針的結構體,'mac'是環境宏

wproc_result結構體是關鍵——它是工作進程執行命令后返回給主引擎的信息包,包含所有必要數據:執行的命令、插件標準輸出(outstd)、標準錯誤(outerr)和退出狀態(源自wait_status)。

概念上的wproc_run_check(或run_scheduled_*_check使用的類似內部函數)接收檢查細節,并將其發送到工作系統進行異步執行。

工作進程內部,實際運行插件命令和捕獲輸出的代碼使用runcmd庫。

runcmd_open函數是啟動命令的起點:

// 摘自 lib/runcmd.h(簡化版)
/*** 從命令行字符串啟動命令* @param[in] cmd 要執行的命令* @param[out] pfd 子進程stdout文件描述符* @param[out] pfderr 子進程stderr文件描述符* // ... 其他參數 ...* @return 子進程pid,或負錯誤碼*/
extern int runcmd_open(const char *cmd, int *pfd, int *pfderr, /* ... */);/*** 等待命令退出并獲取狀態* @param[in] pid runcmd_open啟動的子進程ID* @param[out] status 來自waitpid()的等待狀態* @return 成功返回pid,錯誤返回-1*/
extern pid_t runcmd_wait(pid_t pid, int *status);
  • 工作進程接收到檢查任務后,使用runcmd_open啟動插件。

  • 該函數fork新進程,為標準輸出和標準錯誤建立管道(返回文件描述符pfdpfderr),并執行插件命令。

  • 工作進程從pfdpfderr讀取數據直到關閉(表示插件完成輸出),然后對返回的pid使用runcmd_wait(封裝waitpid)獲取插件退出status

  • 捕獲的數據隨后存入前文提到的wproc_result結構體并返回主引擎。

lib/wproc.c文件包含工作進程的實現代碼,包括監聽任務請求的循環和調用runcmd_open讀取結果的代碼。

示例lib/wproc.c中的print_input函數展示了進程(如Nagios主引擎)如何從工作進程套接字讀取結構化結果(簡化為鍵值對的wproc_result消息)。

用例

通過使用檢查執行系統(由工作進程使用runcmd等工具協調),Nagios Core成功運行"Web Server 1"的check_http插件,獲取關鍵信息:文本輸出(“HTTP OK: …”)和退出代碼(0表示正常,其他值表示問題)。

這些信息是Nagios引擎更新內存狀態數據(狀態數據管理)和status.dat文件的原始材料,最終顯示在CGI界面中。

總結

檢查執行機制通過運行實際外部插件,將監控配置轉化為具體行動。

它將對象定義中的check_command轉換為可執行進程,管理其執行(通常通過輔助工作進程),并捕獲關鍵輸出和退出代碼。

這些結果是Nagios判斷主機和服務狀態的核心依據。

然而我們多次提到"工作進程"卻未完整解釋。Nagios如何管理與這些獨立輔助進程的啟動和通信?這正是下一章要探討的內容。

第七章:工作進程

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/89447.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/89447.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/89447.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Web3 常用前端庫介紹

一、Web3 前端開發:連接用戶與區塊鏈的橋梁 隨著 Web3 生態的蓬勃發展,前端開發從傳統的頁面渲染進化為區塊鏈交互的核心樞紐。Web3 前端庫作為連接用戶與區塊鏈的橋梁,承擔著錢包集成、合約交互、數據可視化等關鍵功能。本文將系統解析主流 …

cnpm命令報internal/modules/cjs/loader.js:797 throw err; ^ Error: Cannot find

在運行一個項目的時候,需要升級電腦各組件的版本,結果導致cnpm命令無法正常使用,cnpm任何命令都會報如下這個錯:找了半天,發現是由于cnpm與npm的版本不一致導致的,所以需要卸載并重新安裝cnpm,重…

15、鴻蒙Harmony Next開發:創建自定義組件

目錄 自定義組件的基本用法 自定義組件的基本結構 struct Component freezeWhenInactive build()函數 Entry EntryOptions Reusable 成員函數/變量 自定義組件的參數規定 build()函數 自定義組件生命周期 自定義組件的創建和渲染流程 自定義組件重新渲染 自定義…

深入理解Map.Entry.comparingByValue()和Map.Entry.comparingByKey()

文章目錄深入理解Map.Entry.comparingByValue()和Map.Entry.comparingByKey()1. 方法定義comparingByKey()comparingByValue()2. 基本用法2.1 使用comparingByKey()2.2 使用comparingByValue()3. 方法重載版本comparingByKey(Comparator)comparingByValue(Comparator)4. 高級用…

Mac下載mysql

安裝 brew list --versions | grep mysql查看已安裝的mysql版本brew search mysql查看支持的mysql版本brew info mysql查看mysql版本信息brew install mysql進行安裝/opt/homebrew/opt/mysql/bin/mysqld --initialize-insecure --user$(whoami) --basedir$(brew --prefix mysql…

PageHelper使用說明文檔

文章目錄一、簡介二、集成步驟三、使用方法四、注意事項五、高級用法一、簡介 PageHelper 是一個開源的 MyBatis 分頁插件,它可以幫助我們在使用 MyBatis 進行數據庫操作時方便地實現分頁功能。通過簡單的配置和少量的代碼修改,就可以在查詢數據時實現分…

grpo nl2sql qwen3 模型強化學習訓練有效果的成立條件有哪些

在使用GRPO(強化學習算法)對Qwen3模型在NL2SQL(自然語言到SQL轉換)任務上進行強化學習(RL)訓練時,其效果成立的核心條件可歸納為以下幾個關鍵維度,這些條件相互關聯,共同…

面向向量檢索的教育QA建模:九段日本文化研究所日本語學院的Prompt策略分析(6 / 500)

面向向量檢索的教育QA建模:九段日本文化研究所日本語學院的Prompt策略分析(6 / 500) 系列說明 500 所日本語言學校結構化建模實戰,第 6 篇。每篇拆解 1 所學校在 Prompt-QA 系統中的建模策略,分享工程經驗,…

墨刀原型圖的原理、與UI設計圖的區別及轉換方法詳解-卓伊凡|貝貝

墨刀原型圖的原理、與UI設計圖的區別及轉換方法詳解-卓伊凡|貝貝最近有個設計由于時間比較倉促直接用 原型做的,但是原型做的大家都知道是沒法用的,以下講解原型和ui的區別,其次我們下面有三種方法把墨刀的原型變成UI圖。一、墨刀原型圖的原理…

前端 nodejs vue2 開發環境和微信開發環境 故障終極處理

現象某個vue2舊項目 引入vue-ls 組件等組件,沖突失敗后刪除,導致開發環境 vxe-table加載失敗,還原后還是不行。前段項目崩潰。報警sass 某個方法 Deprecated ,之前不會處理方式_失敗回退代碼項目代碼 刪除 node_modules, 刪除 …

【后端】.NET Core API框架搭建(9) --配置使用Log4Net日志

目錄 1.添加包 2.新建公用類 3.新建配置 4.注冊 4.1.類庫項目設置 5.使用 在 .NET Core 項目中使用 Log4Net 做日志記錄,具有很多優勢。盡管 .NET Core 自帶了 ILogger 接口(如使用內置的 ConsoleLogger、DebugLogger 等),但…

Agent交互細節

本文參考了https://www.bilibili.com/video/BV1v9V5zSEHA/視頻及原作者代碼實踐 本文主要實踐在第3節1、MCP MCP官方地址:https://modelcontextprotocol.io/introduction MCP 是一個開放協議,它規范了應用程序向 LLM 提供上下文的方式。 架構&#xff1a…

AI+醫療!VR和MR解剖學和針灸平臺,智能時代如何重塑健康未來

在智能時代,“AI醫療”正從精準診斷入手,推動醫療系統變革,通過個性化健康管理、智能診療輔助等方式重塑健康未來!將人工智能(AI)與虛擬實境(VR)應用到中醫教學,透過該系…

Sersync和Rsync部署

學習參考連接 以下是我在學習過程中借鑒的經驗和下載資源鏈接,感謝幾位大佬的幫助,也供各位參考。 Rsync踩坑: https://blog.csdn.net/XiaoXiaoYunXing/article/details/120160395 Sersync下載源 http://down.whsir.com/downloads/sersy…

Django基礎(四)———模板常用過濾器

前言上篇文章給大家介紹了DTL模板的部分知識點這篇文章繼續帶大家深入理解Django框架中的模板過濾器一、模板常用過濾器1.add將傳進來的參數添加到原來的值上面。這個過濾器會嘗試將值和 參數轉換成整形然后進行相加。如果轉換成整形過程中失敗了,那么會將值和參數進…

國內MCP服務器搜索引擎有哪些?MCP導航站平臺推薦

在人工智能技術蓬勃發展的今天&#xff0c;AI模型與外部工具和服務的交互能力正成為推動技術進步的關鍵。AIbase&#xff08;<https://mcp.aibase.cn/>&#xff09;作為一個專注于MCP(Model Context Protocol&#xff0c;模型上下文協議)服務器的集合平臺&#xff0c;為全…

Python中with的作用和用法

在這里我們來詳細解釋一下Python中非常重要的 with 語句。 我會從 “為什么需要它” 開始&#xff0c;然后講解 “它是什么以及如何使用”&#xff0c;最后深入到 “它的工作原理” 和 “如何自定義”。1. 為什么需要 with 語句&#xff1f;(The Problem) 在編程中&#xff0c;…

緩存雪崩、緩存穿透,緩存擊穿

Redis是一個完全開源免費的高性能非關系型&#xff08;NOSQL&#xff09;的key-value數據庫。 Redis不可能把所有的數據都緩存起來(內存昂貴且有限)&#xff0c;所以Redis需要對數據 設置過期時間&#xff0c;并采用的是惰性刪除定期刪除兩種策略對過期鍵刪除。Redis對過期鍵的…

springmvc跨域解決方案

在Spring MVC中處理跨域請求&#xff08;CORS&#xff0c;Cross-Origin Resource Sharing&#xff09;通常涉及到配置HTTP響應頭&#xff0c;以允許來自不同源的請求。Spring MVC提供了多種方式來配置CORS&#xff0c;包括全局配置和局部配置。 使用CrossOrigin注解 在控制器的…

btstack移植之安全配對(二)

3.13.3 Legacy配對首先&#xff0c;我們回復的paring response中&#xff0c;可以看到我們不支持secure connection&#xff0c;所以我們走的是legacy配對模式。圖3-74 secure連接不支持然后&#xff0c;master在pairing confirm包中回復了confirm value。圖3-75 master發送con…