Background: 维护的Win10机器太多,有时需要reboot,一台一台手工太慢。
Solution:
(方法A) 利用Powershell的Restart-Computer 远程reboot 。这里根据协议又可以细分为默认DCOM和指定WSMan两种方法。这里只提DCOM的方法,WSMan与Powershell本身远程有密切关系,可以后面再探究。
(方法B) 用Invoke-Command远程执行Restart-Computer
要求:机器都在一个网段内,能相互访问。
结论:方法A与B都可以远程reboot
必要条件:
Remote端机器的要求
1. 彻底关闭firewall (public/private/domain)或者
或 Firewall必须允许Windows Remote Management 通过,推荐其他几个也允许。
2. 启动有admin权限的powershell,
(1) 执行 Enable-PSRemoting -SkipNetworkProfileCheck -force
(2) winrm quickconfig 确保执行默认没有提示异常。比如如下
WinRM service is already running on this machine.
WSManFault
Message
ProviderFault
WSManFault
Message = WinRM firewall exception will not work since one of the network connection types on this machine is set to Public. Change the network connection type to either Domain or Private and try again.
Error number: -2144108183 0x80338169
WinRM firewall exception will not work since one of the network connection types on this machine is set to Public. Change the network connection type to either Domain or Private and try again.
如果出现了,就要执行Set-NetConnectionProfile -NetworkCategory private 绕过这个限制。再次执行winrm quickconfig 。成功的话见到下面提示
PS C:\WINDOWS\system32> winrm quickconfig
WinRM service is already running on this machine.
WinRM is not set up to allow remote access to this machine for management.
The following changes must be made:
Enable the WinRM firewall exception.
Configure LocalAccountTokenFilterPolicy to grant administrative rights remotely to local users.
Make these changes [y/n]? y
WinRM has been updated for remote management.
WinRM firewall exception enabled.
Configured LocalAccountTokenFilterPolicy to grant administrative rights remotely to local users.
3. 必要的service
主控机(发起reboot要求的)
1. 默认用Restart-Computer的DCOM协议,使用下面code达成并发重启多台目的。这里的Code适用于默认的Win10 Powershell 5.1。
#https://theitbros.com/the-rpc-server-is-unavailable-0x800706ba/
#A. Disable Firewall OR
#B.1 on active Firewall ,enable | allow Windows Management on private & public network
#B.2 Make sure Windows Mangement service is running
#To confirm : On active Firewall ,create new inbound rule:TCP port within range 49152 to 65535
$user_1="share"
$pass_1= "Aa123456"
$secured_pass_1=ConvertTo-SecureString -String $pass_1 -AsPlainText -Force
$credential_1= New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $user_1 , $secured_pass_1
$restartBlock={
param($computername , $cred)
Write-Output "timeout=6 minutes , restarting "$computername #Job won't output info to console , Receive-Job is the only way to receive
#shutdown -m is another way remote restart machines ,however , before invcation , net use /user is demanded
Restart-Computer -ComputerName $computername -force -Credential $cred -Wait -Timeout 600 #credential must be passed in , as scriptBlock could not access variables outside
}
$machines_1=@("10.176.33.196")
[System.Collections.ArrayList]$jobs=@() #Normal Array is of fixed size , I must empoyee ArrayList
$completedJobs=New-Object -TypeName "System.Collections.ArrayList"
#Restart-Computer -ComputerName 10.176.33.206 -force -Credential $credential_2
foreach ($machine in $machines_1)
{
$job= Start-Job -ScriptBlock $restartBlock -ArgumentList $machine , $credential_1
$jobs.Add($job)
}
$quit=$jobs.Count
while ($quit -ne 0)
{
foreach ($job in $jobs)
{
if ($job.State -eq "Running")
{
$info=Receive-Job -Job $job 6>&1
if($info)
{
Write-Host $info
}
}
if ((($job.State -eq "Completed") -or ($job.State -eq "Failed")) -and (-Not $completedJobs.Contains($job)))
{
$info=Receive-Job -Job $job 6>&1
if($info)
{
Write-Host $info
}
Write-Host "Job Completed : $($job|Select-Object Name,State)"
$quit--
if ($quit -eq 0)
{
return
}
$completedJobs.Add($job)
}
}
Start-Sleep 5
Write-Host "$quit Jobs are still running"
}
2. 可以先reboot一台远程机器试试,看是否有异常,比如:a. Access is Denied b. PRC is unavialable
如果使用Invoke-Command也成功执行,如下图,前提条件如上面要求
利用Ws-Man还能远程执行其他各种命令,比如列出远程内容。非常强大
各种异常情况diagnostic:
2. 尝试主控机上用Enter-PSSession -ComputerName x.x.x.x -Credential $MyCredential的方式连接远程,看看有啥报错。正常如下
PS C:\WINDOWS\system32> Enter-PSSession -ComputerName 10.176.33.131 -Credential $credential_1
[10.176.33.131]: PS C:\Users\share\Documents> exit
PS C:\WINDOWS\system32>
踩到的坑: remote端已经关闭了firewall,结果报Access is denied。最后发现必须远程端成功执行winrm quickconfig,估计是要达到"Configured LocalAccountTokenFilterPolicy to grant administrative rights remotely to local users."这个条件。
另一参考文档,感觉本地和remote端执行winrm set winrm/config/client @{TrustedHosts="*"} 与Restart-Computer无关。