You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:编写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的配置文件里加这个命令,比如:
    command[restart_services]=/path/to/你的脚本.sh $ARG1$
    
    然后在Nagios那边配置内存告警触发这个NRPE命令就行。

另外,如果是在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 04:09:49