求助:编写Nagios事件处理Bash脚本实现服务顺序重启
搞定Windows服务器内存过高时的服务顺序重启需求
嘿,作为Bash脚本新手,你这个场景其实挺典型的——用Nagios+NRPE监测到内存占用90%时,按顺序重启指定的4个服务,还得确保前一个服务完全就绪后再动下一个对吧?我给你整理了两种靠谱的实现方案,还有一些踩坑提示,帮你把脚本补全:
方案一:逐个启停(适合有依赖的服务)
这种方式是对每个服务单独执行「停止→确认停止→启动→确认启动」,完美适配服务之间有依赖关系的场景,保证不会因为启动顺序乱了出问题:
#!/bin/bash # 先把这里的服务名换成你实际的Windows服务真实名称(不是显示名!) SERVICES=("ServiceA" "ServiceB" "ServiceC" "ServiceD") # 处理NRPE传过来的状态参数 case "$1" in OK) # 内存正常啥也不用干 exit 0 ;; WARNING) # 警告状态可以记个日志,方便后面查 logger "内存占用警告,暂不执行操作" exit 0 ;; CRITICAL) logger "内存占用触发临界值,开始执行服务重启流程" # 遍历每个服务逐个处理 for SERVICE in "${SERVICES[@]}"; do echo "正在停止服务:$SERVICE" # 如果是本地Windows用sc命令,远程的话换成psexec \\你的服务器IP sc stop "$SERVICE" sc stop "$SERVICE" # 等服务完全停掉再往下走 while sc query "$SERVICE" | grep -q "RUNNING"; do echo "等待$SERVICE停止中..." sleep 5 done echo "$SERVICE已停止" echo "正在启动服务:$SERVICE" sc start "$SERVICE" # 等服务完全启动成功 until sc query "$SERVICE" | grep -q "RUNNING"; do echo "等待$SERVICE启动中..." sleep 5 done echo "$SERVICE已正常运行" done logger "所有服务已完成重启" exit 0 ;; UNKNOWN) logger "收到Nagios传来的未知状态" exit 3 ;; *) echo "用法:$0 {OK|WARNING|CRITICAL|UNKNOWN}" exit 1 ;; esac
方案二:先停所有再逐个启动(适合无依赖的服务)
如果你的4个服务之间没什么依赖关系,先批量停止所有服务,再逐个启动,效率会更高一点:
#!/bin/bash SERVICES=("ServiceA" "ServiceB" "ServiceC" "ServiceD") case "$1" in OK) exit 0 ;; WARNING) logger "内存占用警告,暂不执行操作" exit 0 ;; CRITICAL) logger "内存占用触发临界值,开始执行服务重启流程" # 第一步:先把所有服务都停了 echo "正在停止所有服务..." for SERVICE in "${SERVICES[@]}"; do echo "停止$SERVICE..." sc stop "$SERVICE" done # 等所有服务都停稳 echo "等待所有服务停止..." ALL_STOPPED=false while [ "$ALL_STOPPED" = false ]; do ALL_STOPPED=true for SERVICE in "${SERVICES[@]}"; do if sc query "$SERVICE" | grep -q "RUNNING"; then ALL_STOPPED=false sleep 3 break fi done done echo "所有服务已全部停止" # 第二步:逐个启动每个服务并确认 for SERVICE in "${SERVICES[@]}"; do echo "启动$SERVICE..." sc start "$SERVICE" until sc query "$SERVICE" | grep -q "RUNNING"; do echo "等待$SERVICE启动中..." sleep 5 done echo "$SERVICE已正常运行" done logger "所有服务已完成重启" exit 0 ;; UNKNOWN) logger "收到Nagios传来的未知状态" exit 3 ;; *) echo "用法:$0 {OK|WARNING|CRITICAL|UNKNOWN}" exit 1 ;; esac
几个一定要注意的点!
- 服务名称要准确:别用服务的显示名称(比如「MySQL服务」),要用真实名称!你可以在Windows上运行
sc query命令查看所有服务的真实名称。 - 权限不能少:执行脚本的账号(不管是NRPE运行账号还是远程执行的账号)必须有启停Windows服务的权限,不然会报错。
- 等待时间可以调:脚本里的
sleep 5是等服务启停的时间,如果你的服务启动慢,可以改成sleep 10或者更久,避免判断出错。 - 日志要留好:用
logger记录操作日志,后面出问题了好排查。 - NRPE要配置对:记得在NRPE的配置文件里加这个命令,比如:
然后在Nagios那边配置内存告警触发这个NRPE命令就行。command[restart_services]=/path/to/你的脚本.sh $ARG1$
另外,如果是在Windows本地用NSClient++执行脚本,其实用PowerShell更顺手,给你补个简化版的PowerShell脚本参考:
param($status) $services = @("ServiceA", "ServiceB", "ServiceC", "ServiceD") switch ($status) { "OK" { exit 0 } "WARNING" { Write-EventLog -LogName Application -Source "NRPE脚本" -EventID 100 -EntryType Information -Message "内存占用警告,暂不执行操作" exit 0 } "CRITICAL" { Write-EventLog -LogName Application -Source "NRPE脚本" -EventID 101 -EntryType Information -Message "内存占用触发临界值,开始执行服务重启流程" foreach ($service in $services) { Write-Host "停止$service..." Stop-Service -Name $service -Force Wait-Service -Name $service -Status Stopped -Timeout 60 Write-Host "$service已停止" Write-Host "启动$service..." Start-Service -Name $service Wait-Service -Name $service -Status Running -Timeout 60 Write-Host "$service已运行" } Write-EventLog -LogName Application -Source "NRPE脚本" -EventID 102 -EntryType Information -Message "所有服务重启完成" exit 0 } "UNKNOWN" { Write-EventLog -LogName Application -Source "NRPE脚本" -EventID 103 -EntryType Error -Message "收到Nagios未知状态" exit 3 } default { Write-Host "用法:$($MyInvocation.MyCommand.Name) {OK|WARNING|CRITICAL|UNKNOWN}" exit 1 } }
内容的提问来源于stack exchange,提问作者Steve Proschenko
相关产品推荐
相关产品推荐

