如何通过SSH协议使用PowerShell实现远程电脑重启并等待完成
如何通过SSH协议使用PowerShell实现远程电脑重启并等待完成
刚好碰到过类似的需求,给你分享个可行的方案!因为Restart-Computer的-Wait参数确实只支持WinRM,所以咱们得自己实现SSH环境下的重启+等待逻辑,步骤其实不难:
前提准备
首先得确保几个基础条件:
- 目标电脑已经开启SSH服务,防火墙允许22端口入站
- 你本地用的是PowerShell 7及以上版本(只有这个版本原生支持SSH作为远程协议)
- 远程SSH账号拥有管理员权限(毕竟重启电脑需要权限)
实现思路
先通过SSH远程发送重启命令,然后循环检测远程主机的SSH服务是否恢复正常——毕竟ping通不代表SSH服务已经启动,直接检测SSH连接才是最准确的。
具体脚本实现
单次执行的简易版本
# 定义参数 $remoteHost = "你的远程主机名/IP" $userName = "远程SSH账号" $waitInterval = 10 # 每次检测间隔10秒 $maxRetries = 30 # 最多等待5分钟(30*10秒) # 第一步:发送远程重启命令 try { Invoke-Command -HostName $remoteHost -UserName $userName -ScriptBlock { Restart-Computer -Force } -ErrorAction Stop Write-Host "已向 $remoteHost 发送强制重启命令" } catch { Write-Error "发送重启命令失败:$_" exit 1 } # 第二步:循环等待SSH连接恢复 $retryCount = 0 $isRestartCompleted = $false while ($retryCount -lt $maxRetries -and -not $isRestartCompleted) { Start-Sleep -Seconds $waitInterval $retryCount++ Write-Host "等待重启中... 第 $retryCount 次尝试(剩余 $($maxRetries - $retryCount) 次)" try { # 先测试SSH端口是否开放 $tcpClient = New-Object System.Net.Sockets.TcpClient $tcpClient.Connect($remoteHost, 22) $tcpClient.Close() # 再尝试建立SSH会话,确认服务正常 $session = New-PSSession -HostName $remoteHost -UserName $userName -ErrorAction Stop Remove-PSSession $session $isRestartCompleted = $true Write-Host "✅ $remoteHost 重启完成,SSH连接已恢复!" } catch { Write-Host "⚠️ $remoteHost 暂未恢复:$($_.Exception.Message)" } } # 超时处理 if (-not $isRestartCompleted) { Write-Error "❌ $remoteHost 重启超时,超过 $($maxRetries*$waitInterval) 秒未恢复SSH连接" exit 1 }
可复用的函数版本
如果需要多次使用,可以把逻辑封装成函数:
function Restart-RemoteComputerViaSSH { [CmdletBinding()] param( [Parameter(Mandatory=$true, HelpMessage="远程主机名或IP")] [string]$HostName, [Parameter(Mandatory=$true, HelpMessage="远程SSH账号")] [string]$UserName, [Parameter(HelpMessage="检测间隔(秒)")] [int]$WaitInterval = 10, [Parameter(HelpMessage="最大重试次数")] [int]$MaxRetries = 30 ) # 发送重启命令 try { Invoke-Command -HostName $HostName -UserName $UserName -ScriptBlock { Restart-Computer -Force } -ErrorAction Stop Write-Host "已向 $HostName 发送强制重启命令" } catch { Write-Error "发送重启命令失败:$_" return } # 等待重启完成 $retryCount = 0 $isOnline = $false while ($retryCount -lt $MaxRetries -and -not $isOnline) { Start-Sleep -Seconds $WaitInterval $retryCount++ Write-Verbose "等待重启中... 第 $retryCount 次尝试" try { # 测试SSH端口 $tcpClient = New-Object System.Net.Sockets.TcpClient $tcpClient.Connect($HostName, 22) $tcpClient.Close() # 验证会话可建立 $session = New-PSSession -HostName $HostName -UserName $UserName -ErrorAction Stop Remove-PSSession $session $isOnline = $true Write-Host "✅ $HostName 重启完成!" } catch { Write-Verbose "$HostName 未恢复:$($_.Exception.Message)" } } if (-not $isOnline) { Write-Error "❌ $HostName 重启超时,超过 $($MaxRetries*$WaitInterval) 秒未恢复" } } # 使用示例(加-Verbose可以看详细日志) Restart-RemoteComputerViaSSH -HostName "RemotePC01" -UserName "AdminUser" -Verbose
一些注意事项
- 如果目标电脑重启速度较慢,可以适当调大
$MaxRetries或者$WaitInterval参数 - 如果你已经配置了SSH密钥免密登录,就不用每次输入密码了,脚本会自动使用密钥认证
- 执行
Restart-Computer -Force会强制关闭所有正在运行的程序,如果你需要优雅重启,可以去掉-Force参数,但可能会因为程序未响应导致重启延迟
备注:内容来源于stack exchange,提问作者Jellyfish




