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
相关产品推荐
相关产品推荐

