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

PowerShell脚本满足退出条件不退出且触发失败条件后无限循环问题

PowerShell服务重启告警脚本问题修复

需求说明

编写用于在服务器上启停服务的PowerShell脚本,期望重启操作失败时脚本可发送邮件告警。设计逻辑为:先停止服务,休眠数秒后检查服务状态,若服务未运行则尝试启动,启动后休眠再检查;每次启动失败重试次数加1,重试次数超过最大阈值时触发失败通知,若服务处于Running状态则标记重启操作完成并退出循环。

遇到的问题

  • 第一次运行脚本时,进入循环检查服务后错误标记重启完成,实际检查时服务处于停止状态
  • 第二次运行脚本时,停止服务进入循环后尝试重启服务,循环3次后触发预设的邮件告警失败条件,但脚本会持续在失败条件中循环几十次,直到手动强制退出才停止

根因分析

  • 服务状态检查逻辑错误:$service变量仅在脚本初始化时执行了一次Get-Service获取状态,后续循环过程中没有实时更新服务状态,始终读取的是脚本启动时的缓存状态,导致状态判断完全失准
  • 失败分支无退出逻辑:重试次数超过阈值触发告警后,既没有修改循环判断变量$restartComplete,也没有退出脚本的逻辑,导致脚本会持续卡在告警分支无限循环

原错误代码

$VerbosePreference = "continue"
$remoteServer = 'My-RemoteServer01' 
$serviceName = 'MSSQLServerOLAPService'
$service = Get-Service -name $ServiceName
$maxRetries = 2
$retryCount = 0
$restartComplete = $false

stop-service -name $serviceName
write-verbose 'Service Stopped - Sleep 15s'
start-sleep -s 15

write-verbose "Attempt to restart service '$retryCount' "

while ($restartComplete -eq $false){
     if ($service.status -eq 'Running')
        {
         $restartComplete = $true
         write-verbose "restart complete"
         }
         else {
               if ($retryCount -ge $maxRetries)   
                  { 
                   write-verbose "Service Restart Failed - Begin Alert"

                   $smtpServer = ('smtp.mymailserver.com', 00)
                   $msg = new-object Net.Mail.MailMessage
                   $smtp = new-object Net.Mail.SmtpClient($smtpServer)
                   $dateString = get-date

                   $msg.From = 'no-reply@mymailserver.com'
                   $msg.To.Add('L3LYZA@mymailserver.com')
                   $msg.subject = 'URGENT ALERT - Service ' + $service + 'is' + $service.status + 'on' + $remoteServer + '.'
                   $msg.body = ([string]$dateString) + 'Service' + $service + 'is' + $service.status + 'on' + $remoteServer + '.'
                   $smtp.send($msg)

                   write-verbose "Alert Sent - Complete"
                   }
                  else {                 
                        if ($service.status -ne 'Running')   
                           { 
                            start-service -name $serviceName
                            write-verbose 'Service Restarting - Sleep 45s'
                            start-sleep -s 45
                            $retryCount++

                           }
                   }
           }
   }

修复方案

  • 调整服务状态检查方式:循环内每次判断状态都实时执行Get-Service获取最新的服务状态,避免读取缓存的旧数据
  • 失败分支添加退出逻辑:告警发送完成后执行Throw语句终止脚本,避免无限循环

修复后代码

$VerbosePreference = "continue"
$remoteServer = 'My-RemoteServer' 
$serviceName = 'MSSQLServerOLAPService'
$service = Get-Service -name $ServiceName
$maxRetries = 2
$retryCount = 0
$restartComplete = $false

stop-service -name $serviceName
write-verbose 'Service Stopped - Sleep 15s'
start-sleep -s 15

write-verbose "Attempt to restart service '$break' "

while ($restartComplete -eq $false){
     if ((Get-Service $serviceName).Status -eq 'Running')
        {
         $restartComplete = $true
         write-verbose "restart complete"
         }
         else {
               if ($retryCount -ge $maxRetries)   
                  { 
                   write-verbose "Service Restart Failed - Begin Alert"

                   $smtpServer = ('smtp.mymailserver.com', 00)
                   $msg = new-object Net.Mail.MailMessage
                   $smtp = new-object Net.Mail.SmtpClient($smtpServer)
                   $dateString = get-date

                   $msg.From = 'noreply@mymailserver.com'
                   $msg.To.Add('L3LYZA@mymailserver.com')
                   $msg.subject = 'URGENT ALERT - Service ' + $service + 'is' + $service.status + 'on' + $remoteServer + '.'
                   $msg.body = ([string]$dateString) + 'Service' + $service + 'is' + $service.status + 'on' + $remoteServer + '.'
                   $smtp.send($msg)

                   write-verbose "Alert Sent - Complete"
                   Throw "service restart failed exit condition met"
                   }
                  else {                 
                        if ((Get-Service $serviceName).Status -ne 'Running')   
                           { 
                            start-service -name $serviceName
                            write-verbose 'Service Restarting - Sleep 45s'
                            start-sleep -s 45
                            $retryCount++

                           }
                    }
            }
   }

内容的提问来源于stack exchange,提问作者L3LYZA

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 12:36:03