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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 18:37:02