PowerShell服务器重启脚本日志输出异常问题求助
PowerShell重启服务器脚本日志异常排查
问题描述
这是此前发布的「PowerShell输出日志显示错误信息」问题的跟进。当前修改的PowerShell脚本可从TXT读取服务器列表并执行重启,重启功能正常,但日志输出存在两个异常:
- 日志未列出服务器列表中的所有系统(共13台,仅显示3台)
- 日志中记录的脚本执行时间
$Date晚于服务器$LastBoot时间,且存在服务器名称为空、启动时间显示异常的情况
当前核心代码
#For privacy reasons, the actual file path is replaced with "File Path" Clear-Host $YN = Read-Host -Prompt "CONFIRM REBOOT [Y/N]" if(($YN -eq "Y") -or ($YN -eq "y")) { Get-ChildItem -Path "\\File Path\Logs\Restart Logs" -Recurse -File | Move-Item -Destination "\\File Path\Restart Logs\Archive" -Force $ScriptDir = Split-Path $script:MyInvocation.MyCommand.Path $Log = New-Item "\\File Path\Logs\Restart Logs\$(Get-Date -f yyyy-MM-dd_hh-mm-ss) Restarts.txt" -ItemType File -Force $Date = Get-Date -Format "dd-MMM-yyyy hh:mm:ss" $Now = [datetime]::Now Clear-Host Write-Host `n `n `n Write-Host "Rebooting all servers and verifying reboot status..." `n `n Write-Host "Please standby, process may take up to 30 minutes..." `n `n Restart-Computer -ComputerName $Servers -Wait -For PowerShell -Delay 2 -Force -Timeout 1800 "----------------------------------Script executed on $Date----------------------------------" + "`r`n" | Out-File $Log -Append foreach($Server in $Servers) { $LastBoot = (Get-CimInstance Win32_OperatingSystem -ComputerName $Server -EA 0).LastBootUpTime $PingRequest = Test-Connection -ComputerName $Server -Count 1 -Quiet if(($PingRequest -eq $true) -and ($LastBoot -gt $Now)) { Add-Content -Path $Log -Value "$Server`: Reboot Successful." } elseif ($PingRequest -eq $false) { Add-Content -Path $Log -Value "$Server`: Server not detected, please confirm." } else { #"Last detected boot up time is $LastBoot" added since previous question for testing Add-Content -Path $Log -Value "$Server`: Restart not detected, please restart server manually. Last detected boot up time is $LastBoot" } } Clear-Host Write-Host `n `n `n Write-Host "All done!" `n Write-Host "Please review logs, as script may have run into problems." `n `n Log-Location Pause } else { Clear-Host Write-Host `n `n `n Write-Host "Server Reboots Aborted." `n `n Pause }
日志示例
----------------------------------Script executed on 06-Jun-2024 09:50:44---------------------------------- -Redacted-: Restart not detected, please restart server manually. Last detected boot up time is 06/06/2024 21:40:08 : Restart not detected, please restart server manually. Last detected boot up time is 05/21/2024 20:39:16 FakeServerNameForTesting: Server not detected, please confirm.
问题排查与修复方案
1. 日志未列出所有服务器的原因及修复
原因分析
Restart-Computer阻塞导致循环中断:Restart-Computer -Wait -For PowerShell会等待所有服务器恢复PowerShell连接后才继续执行。若某台服务器重启后无法恢复连接,脚本会卡在该步骤直到超时(30分钟),超时后可能因$Servers变量异常或执行中断,导致仅部分服务器被处理。- 服务器列表存在无效条目:从TXT读取
$Servers时,若未过滤空行、空格或特殊字符,会导致循环时跳过或出错,无法输出所有服务器日志。
修复方案
- 拆分重启与等待逻辑:改用异步重启,避免单台服务器阻塞整个流程:
# 异步重启所有服务器,不等待 Restart-Computer -ComputerName $Servers -Force -AsJob # 等待所有重启任务完成 Get-Job | Wait-Job | Remove-Job - 预处理服务器列表:读取时过滤空行和无效条目:
# 假设服务器列表来自TXT文件,添加过滤逻辑 $Servers = Get-Content "服务器列表路径.txt" | Where-Object { $_ -match '\S' } | ForEach-Object { $_.Trim() } - 添加循环异常捕获:避免单台服务器的错误终止整个循环:
foreach($Server in $Servers) { try { $LastBoot = (Get-CimInstance Win32_OperatingSystem -ComputerName $Server -ErrorAction Stop).LastBootUpTime $PingRequest = Test-Connection -ComputerName $Server -Count 1 -Quiet -ErrorAction Stop # 原有状态判断逻辑 } catch { Add-Content -Path $Log -Value "$Server`: 检查时发生错误:$($_.Exception.Message)" } }
2. 时间异常与空服务器名称的原因及修复
原因分析
- 时间格式混淆:
$Date使用12小时制(hh:mm:ss),而$LastBoot返回24小时制时间,导致上午的脚本时间(09:50)看起来晚于服务器的21:40,属于格式显示问题。 - 空服务器名称:
$Servers中包含空字符串(如TXT存在空行),循环时$Server为空,导致日志出现无名称条目。 Get-CimInstance返回空值:若服务器无法通过CIM访问,-EA 0会让$LastBoot返回$null,后续判断逻辑出错,且日志中显示的$LastBoot可能是残留的旧值。
修复方案
- 统一时间格式与时区:使用24小时制格式,同时统一时区避免差异:
$Date = Get-Date -Format "dd-MMM-yyyy HH:mm:ss" # HH为24小时制 $Now = [datetime]::Now.ToUniversalTime() # 转UTC统一时区 # 获取LastBoot时也转UTC $LastBoot = (Get-CimInstance Win32_OperatingSystem -ComputerName $Server -EA 0).LastBootUpTime?.ToUniversalTime() - 过滤空服务器名称:通过预处理服务器列表确保
$Servers中无空值(参考前文修复方案)。 - 处理
$LastBoot空值情况:在判断前先校验$LastBoot有效性:foreach($Server in $Servers) { $LastBoot = $null $PingRequest = Test-Connection -ComputerName $Server -Count 1 -Quiet if ($PingRequest) { $LastBoot = (Get-CimInstance Win32_OperatingSystem -ComputerName $Server -EA 0).LastBootUpTime } if($PingRequest -and $LastBoot -and $LastBoot -gt $Now) { Add-Content -Path $Log -Value "$Server`: Reboot Successful." } elseif (-not $PingRequest) { Add-Content -Path $Log -Value "$Server`: Server not detected, please confirm." } elseif (-not $LastBoot) { Add-Content -Path $Log -Value "$Server`: Failed to retrieve boot time." } else { Add-Content -Path $Log -Value "$Server`: Restart not detected, please restart server manually. Last detected boot up time is $($LastBoot.ToString('dd-MMM-yyyy HH:mm:ss'))" } }
内容的提问来源于stack exchange,提问作者RustyAndroid
相关产品推荐
相关产品推荐

