Nagios外掛編寫及使用nrpe執行root命令

Michael_DD發表於2014-11-25
Nagios外掛編寫及使用nrpe執行root命令


MicrosoftInternetExplorer402DocumentNotSpecified7.8Normal0
前言:Nagios是相當不錯的監控工具,被稱作是“監控之神”,但同樣也有“難搞死”頭銜。發揮 Nagios一切魅力的都是他的外掛,正因為豐富多樣的外掛讓nagios有血有肉。監控的內容不斷在變化,外掛也不斷變化,預設的一些外掛可能越來越不 能滿足需求,這個時候就要自己來寫些外掛了。
以下就是用我的第一個Nagios外掛來說明編寫方法和我遇到一些問題除錯方法。如果你有耐心可以通篇看完,應該對第一次寫的人來說會有很大幫助(如果你看不懂,可能是我寫得不清楚 那就沒辦法了 表達能力有限)
需求:
監控普通磁碟的健康狀況(普通磁碟以外還有RAID、陣列的監控是不同方法來做的,這裡先不討論,先從最簡單的入手),定期進行檢測,並進行報警,報警內容磁碟是否正常,不正常是什麼狀態。
分析編寫過程:
我寫指令碼的前提都是先從手動成功完成,再到自動化(我想其它人的思路應該都一樣的)
1、找到監控磁碟的方法
透過一番查詢 smartctl 這個命令是比較不錯的  centos slackware一般的預設都有這個
smartctl -H /dev/sda  只檢測狀態
smartctl -i /dev/sda   只檢測硬碟資訊
smartctl -a /dev/sda 檢測所有資訊
2、獲取檢測資訊
# smartctl -H /dev/sda
smartctl version 5.38 [x86_64-redhat-linux-gnu] Copyright (C) 2002-8 Bruce Allen
Home page is
SMART Health Status: OK
關鍵的最後一行說明磁碟的情況       擷取  DISK_HEALTH=`smartctl -H /dev/sda | tail -1 | cut -d: -f2-  `
3、 進行關鍵判斷
據我所知道的 smartctl 5.38  是出以上的結果 為OK
而 smartctl 5.39 是出以下結果
=== START OF READ SMART DATA SECTION ===
SMART overall-health self-assessment test result: PASSED
關鍵詞是PASSED
所以要分析判斷多種情況
4、指令碼編寫步驟
1)瞭解nagios外掛編寫規範
Nagios的外掛可以用指令碼(shell、Perl)C編譯後的可執行程式,但必須滿足以下兩件事:
A、既出時有一個返回值
B、至少向標準輸出裝置(STDOUT)輸出一行檔案。(但也不能太大,預設是4K,如果想大些,修改源程式吧,方法搜。。。)
返回值定義:
Plugin Return Code
Service State
DISK State
0
OK
OK 或者PASSED
1
WARNING
外掛警告  DISK報警只分OK或者CRITICAL
2
CRITICAL
DISK檢測非OK 或者PASSED
3
UNKNOWN
未知狀態
2)外掛編寫SHELL速成法
在這裡我選用我最熟悉的SHELL進行指令碼編寫 ,
我的速成法就是,直接去nagios exchange 去下比較成熟的比較簡單的shell指令碼,這樣會從一開始借鑑別人好的方法,養成好的習慣,而且只要你有一點SHELL程式設計經驗也可以很快寫得像一個老手。(不過不要把自己搞暈了就行)
3)以下是我的check_disk_health.sh
#!/bin/bash
# ========================================================================================
# disk health  plugin for Nagios
#
# Written by    : Ajian
# Release       : 1.2.0
# Creation date : 2009-07-28
# Revision date : 2009-07-30
# Description   : Nagios plugin (script) to check disk health .
#               This script has been designed and written on Linux System.
#
# USAGE         : ./check_disk_health.sh [-d (disk)]
#
# Exemple: ./check_cpu_stats.sh
#          ./check_cpu_stats.sh -d /dev/sda
#
#
# HISTORY :
#     Release   |     Date      |    Authors            |       Description
# --------------+---------------+----------------------+-----------------------------------
#  1.0.0        | 2009-07-28     | Ajian                | Create the script
#  1.2.0        | 2009-07-30    |  Ajian                | modify the script and run well ,fix a bug.
# -----------------------------------------------------------------------------------------
# NOTICE:
#-----------------------------------------------------------------------------------------
#     You should have the root Permissions ,You can use sudo to realize .
# -----------------------------------------------------------------------------------------                                   
 
# Nagios return codes
#定義 nagios返回的狀態變數
STATE_OK=0
STATE_WARNING=1
STATE_CRITICAL=2
STATE_UNKNOWN=3      
 
# Paths to commands used in this script.  These may have to be modified to match your system setup.
# 定義關鍵的核心命令smartctl 路徑 如果你的系統不是這個地址,請更改。 以下注釋的是除錯的資訊,是自動獲取命令路徑的方法。
SMARTCTL="/usr/sbin/smartctl"
#SMARTCTL=`which smartctl`
#if [ $? -ne 0 ]; then
#        echo " smartctl is found in $SMARTCTL ; Go on ... "
#        echo "smartctl the command cannot find"
#        exit $STATE_UNKNOWN
#fi
# Plugin parameters value if not define
# 定義預設的檢測硬碟
CHECK_DISK="/dev/sda"                  
 
# Plugin variable description
# 外掛描述資訊
PROGNAME=$(basename $0)
RELEASE="Revision 1.2.0"
AUTHOR="(c) 2009 Ajian (ajian521@gmail.com)"
 
# Functions plugin usage
# 外掛的使用方法函式
print_release() {
    echo "$RELEASE $AUTHOR"
}                          
 
print_usage() {
        echo ""
        echo "$PROGNAME $RELEASE - Disk health check script for Nagios"
        echo ""
        echo "Usage: check_disk_health.sh -d /dev/sdb"
        echo ""
        echo "  -d  the disk (/dev/sda) "
        echo "          not the Hard disk partition(sda2 is wrong)"
        echo "  -v  check the version"
        echo "  -h  Show this page"
        echo ""
    echo "Usage: $PROGNAME"
    echo "Usage: $PROGNAME --help"
    echo ""
    exit 0
}                                                                                                          
 
print_help() {
        print_usage
        echo ""
        echo "This plugin will check disk health  "
        echo ""
        exit 0
}                                                  
 
# Parse parameters
# 傳遞引數
while [ $# -gt 0 ]; do
    case "$1" in
        -h | --help)
            print_help
            exit $STATE_OK
            ;;
        -v | --version)
                print_release
                exit $STATE_OK
                ;;
        -d | --disk)
                shift
                CHECK_DISK=$1
                #判斷磁碟是否存在
                if [ ! -b $CHECK_DISK ];then
                        echo "$CHECK_DISK is no exsit,Please change it "
                        exit $STATE_CRITICAL
                fi
                ;;
        *)  echo "Unknown argument: $1"
            print_usage
            exit $STATE_UNKNOWN
            ;;
        esac
shift
done
 
#根據不同的操作進行不同的操作,這裡暫時只支援Linux
case `uname` in
        Linux )
             #最核心的部分 前面都是些指令碼的基本功能 一個框架 因為第一個指令碼牽扯到了很多東西,雖然功能很簡單,
             #但折騰了我不少,在後面的分析中會具體說到 總之注意sudo用法 指令碼一開始就有說哦
                DISK_HEALTH=`$SMARTCTL  -H $CHECK_DISK | tail -1 | cut -d: -f2- `
                #DISK_HEALTH="OK"
        #       DISK_INFO=`/usr/bin/sudo $SMARTCTL -i $CHECK_DISK | grep "Device:"`
                if [ "$DISK_HEALTH" = " OK" ]|| [  "$DISK_HEALTH" = " PASSED" ];then
                        echo "OK - $CHECK_DISK status is $DISK_HEALTH "
                        #echo "OK - $CHECK_DISK status is $DISK_HEALTH | $DISK_INFO"
                        exit $STATE_OK
                else
                        echo "CRITICAL - $CHECK_DISK status is $DISK_HEALTH "
                        #echo "CRITICAL - $CHECK_DISK status is $DISK_HEALTH | $DISK_INFO"
                        exit $STATE_CRITICAL
        fi
            ;;
 
        *)              echo "UNKNOWN: `uname` not yet supported by this plugin. Coming soon !"
                        exit $STATE_UNKNOWN
            ;;
        esac
4)執行指令碼
(注意:在最開始自己寫的指令碼是沒有sudo的,以上指令碼是已經除錯過後的,還需要配置一些其它的東西,慢慢看吧)
給與指令碼執行許可權,手動執行
# ./check_disk_health.sh
OK – /dev/sda status is  OK
結果正確了,其實這個時候,高興得太早了。 我先不說問題、繼續正常的一般流程。
5、配置Nagios 呼叫外掛
1)在遠端NRPE 被監控伺服器上修改nrpe.conf
# vim /usr/local/nagios/etc/nrpe.cfg
新增 command[check_sda_health]=/usr/local/nagios/libexec/check_disk_health.sh -d /dev/sda
(注意這裡了,先提醒下,這裡是錯誤的,一般是正確的,是這個指令碼的特殊性造成的)
2)在Nagios 監控伺服器上新增一些配置
定義服務
define service{
use                             Disk-Health
host_name                       DB-56
servicegroups                   Disk-Health
service_description            check sda disk health
contact_groups                  admins
check_command               check_nrpe!check_sda_health
}
如果像上面定義一個服務 那麼就要注意相關的定義了 ,
定義Disk-Health 模版  把硬碟檢測定義一個模版會比較好控制,因為硬碟的檢測不像其它服務一樣需要準確的及時性反正檢測得太多可能會造成壓力,一般一天檢測幾次就夠了。
定義DB-56 主機需要定義
定義組 admins
以上這些只要安裝過nagios 一般都知道的了 只是強調下模版的單獨定義
3)透過WEB控制檢測 檢視結果
結果是失敗 報警CRITCTL 但是狀態裡面的資訊都是空的  CRITCTL – /dev/sda status is
6、除錯
從Nagios的遠端監控來看是失敗的,並且沒有獲取到任務有用的資訊。
分析可以看到,說明nrpe呼叫  這個變數獲取到的是為空的資訊
DISK_HEALTH=`$SMARTCTL -H $CHECK_DISK | tail -1 | cut -d: -f2- `
即是空的 只有一個原因,肯定是沒有執行 如果執行了 肯定會有欄位 不管這個欄位是否相符。
但是手動執行是沒有問題。
經過對smartctl的檢視 原來這個命令是隻允許root進行呼叫的。
現在需要解決的問題是:非root 使用者 如何遠端呼叫含有需要有root許可權命令的指令碼進行監控。
(不要小看這一句話,每一個詞都是一個需要攻克的地方)
以下是除錯步驟:
1)非root使用者
NRPE外掛是用nagios這個使用者來執行的 所以要得到真實的情況需要
A: su nagios   再執行指令碼 (這個方法比較好)
B: sudo -u nagios ./check_disk_health.sh
結果:
sudo -u nagios ./check_disk_health.sh
CRITICAL – /dev/sda status is
跟遠端的結果是一樣的了 沒有資訊
2)需要有root許可權
需要root許可權只有一個辦法就是用sudo
將DISK_HEALTH=`$SMARTCTL -H $CHECK_DISK | tail -1 | cut -d: -f2- `
改為DISK_HEALTH=`/usr/bin/sudo $SMARTCTL -H $CHECK_DISK | tail -1 | cut -d: -f2- `
(最後發現這時加sudo 並不是關鍵 關鍵是很行指令碼時用sudo )
結果:sudo -u nagios ./check_disk_health.sh
Password:
需要輸入密碼  sudo不用輸入密碼的方法
修改sudo配置檔案
執行 visudo
新增
nagios ALL=(ALL) NOPASSWD:/usr/local/nagios/libexec/check_disk_health.sh
建議:最好進行sudo的一些控制,很多網方法就是nagios ALL=NOPASSWD:ALL
結果:
su nagios
/usr/bin/sudo check_disk_health.sh
OK – /dev/sda status is OK
那麼在nrpe.conf配置檔案中需要新增sudo
command[check_sda_health]=/usr/bin/sudo /usr/local/nagios/libexec/check_disk_health.sh
最開始那個是錯誤的 注意啊 這個是需要新增/usr/bin/sudo 就是說只要指令碼中涉及到提升到root許可權的命令那麼就要用這個
3)遠端呼叫
遠端呼叫方法:./check_nrpe -H 192.168.0.56 -c check_sda_health
同上如果想模擬真實環境請切換到相應的執行使用者 su nagios 再執行以上操作
結果:   
這個錯誤的原因一定要明白,之所以報這個錯意思是說NRPE沒有獲取到任何資訊,也說是寫指令碼之前說的其中第二條規範
問題:在沒有任何資訊的情況下怎麼來獲取NRPE執行的日誌呢
就是要確定問題在哪,經過一大番的查詢眼睛偶爾看到一個有趣的小方法
修復nrpe.conf配置檔案 在要檢查的命令後面新增>>/tmp/output 2>&1 將錯誤匯出到檔案中進行檢視
command[check_sda_health]=/usr/bin/sudo /usr/local/nagios/libexec/check_disk_health.sh -d /dev/sda >>/tmp/output 2>&1
重記nrpe服務
遠端呼叫 結果當然還是NRPE: Unable to read output
檢視/tmp/output
sudo: sorry, you must have a tty to run sudo
有錯誤就簡單了  原來這個是預設不允許sudo 在後端進行
visudo
註釋Defaults requiretty 就OK了
結果透過WEB檢視也正確了。
(注意:註釋後 檢測仍然會是Unable 不過看/tmp/output就會有正確的結果,所以有正確的結果後,一定要去掉 >>/tmp/outpt 2>&1 資訊都導到檔案中了 nagios還是得不到任何訊息。)
一個指令碼執行成功後,就是大批次應用,用生產環境驗證,出現問題繼續除錯。
以上為所有的分析除錯方法。如果你看到最後一步了,說明你很有耐心,你也一定會成功的,至於寫得好與壞、對與錯請儘管說,這不會影響你的成功。呵呵

今天在搞nagios 的event handler時除錯了半天沒有結果,把我鬱悶的,最後發現是在visudo裡沒有註釋Defaults requiretty   
註釋後使用 check_nrpe -H 127.0.0.1 -c restart_nginx 命令可以正常工作
restartnginx.sh 內容如下
#*******************************
#Author sky
#20120206
/usr/bin/sudo /usr/local/nginx/sbin/nginx -s stop
/usr/bin/sudo /usr/local/nginx/sbin/nginx
printf "DONE!"
#*********************************

原先還有“NRPE: Unable to read output”錯誤,在指令碼加一行’ printf "DONE!" ‘就可以了
特此備忘一下
明天再繼續搞

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29500582/viewspace-1346010/,如需轉載,請註明出處,否則將追究法律責任。

相關文章