Powershell管理遠程計算機(四)
管理遠程計算機
遠程處理功能
遠程處理是特定 Windows PowerShell 功能的名稱,不要與更通用的遠程連接概念混淆。 遠程處理是一種通用方法,可將任何命令傳輸到遠程計算機,使其在該計算機上進行本地運行。 你運行的命令不必在啟動連接的計算機上可用。
許多 Windows PowerShell cmdlet 都具有 ComputerName 參數,此參數可使你在一臺或多臺遠程計算機上收集數據和更改設置
這些 cmdlet 使用不同的通信協議,無需進行任何特殊配置即可在所有 Windows 操作系統上工作
這些 cmdlet 包括:
- Restart-Computer
- Test-Connection
- Clear-EventLog
- Get-EventLog
- Get-HotFix
- Get-Process
- Get-Service
- Set-Service
- Get-WinEvent
- Get-WmiObject
通常情況下,支持無需特殊配置的遠程處理的 命令 具有 ComputerName 參數,但不具有 Session 參數。
若要在會話中查找這些 cmdlet,請輸入:
Get-Command | where { $_.parameters.keys -contains "ComputerName" -and $_.parameters.keys -notcontains "Session"}
前期準備
- 客戶端和被控主機都需要開啟winrm
winrm quickconfig
- 客戶端需要開啟遠程處理功能
Enable-PSRemoting -Force
這個命令會:
-
啟動 WinRM 服務。
-
將 WinRM 服務的啟動類型設置為“自動啟動”。
-
配置防火墻規則,允許 WinRM 流量通過。
-
信任主機配置
Set-Item wsman:\localhost\client\trustedhosts "遠程計算機IP或名稱"
- 完成后,通常需要重啟 WinRM 服務以使更改生效
Restart-Service WinRM
- 在建立正式連接前,可以先測試遠程計算機是否已準備好接受 PowerShell 遠程連接
Test-WSMan -ComputerName "遠程計算機名或IP"
遠程管理配置檢查清單
為了確保遠程管理功能正常工作,你可以使用以下清單進行檢查:
- 網絡連通性:確保本地計算機與遠程計算機之間網絡暢通(例如,可以互相 ping 通)。
- PowerShell 權限:以管理員身份運行 PowerShell。
- 啟用 PSRemoting:在遠程計算機上已執行
Enable-PSRemoting -Force。 - WinRM 服務狀態:確保遠程計算機上的 WinRM 服務正在運行(
Get-Service WinRM)。 - 防火墻規則:確認防火墻允許 WinRM 流量(通常
Enable-PSRemoting會自動配置)。 - 信任的主機:在工作組環境中,已在本地計算機上使用
Set-Item wsman:\localhost\client\trustedhosts將遠程計算機添加為受信任主機。 - 用戶權限:你使用的憑據在遠程計算機上具有管理員權限。
- 執行策略:遠程計算機的 PowerShell 執行策略(Execution Policy)是否允許運行所需的腳本(可使用
Get-ExecutionPolicy查看,如需設置可使用Set-ExecutionPolicy RemoteSigned) - 是否對面被控主機也開啟了winrm服務
交互式遠程會話(一對一)
要啟動一個交互式的遠程會話(類似于使用 SSH),進入一個仿佛直接操作遠程計算機的命令行環境,可以使用 Enter-PSSession 命令:
Enter-PSSession -ComputerName "遠程計算機名或IP" -Credential "用戶名"
系統會提示你輸入該用戶對應的密碼。執行成功后,命令提示符會變成 [遠程計算機名或IP]: PS> 的格式,表示你當前的操作都在遠程計算機上生效。


要退出交互式會話,回到本地 PowerShell 環境,只需執行:
Exit-PSSession
執行遠程命令和腳本(一對多)
- 執行單條命令
Invoke-Command -ComputerName "遠程計算機名或IP" -ScriptBlock { 你的命令 } -Credential "用戶名"
這里會讓你輸入登錄目標主機的密碼,輸入的密碼是你指定的這個Credential參數的用戶名的密碼
輸入密碼正確就執行成功了


- 執行腳本文件
Invoke-Command -ComputerName "遠程計算機名或IP" -FilePath "本地腳本路徑" -Credential "用戶名"
- 對多臺進行操作
$computers = "Server01", "Server02", "Server03" # 將計算機名或IP放入數組
Invoke-Command -ComputerName $computers -ScriptBlock { 你的命令 } -Credential "用戶名"
Credential參數
上面說了一個就是直接給用戶名沒給密碼,如果希望直接用腳本進行管理的話,每次都需要彈出來窗口上輸入密碼這會比較麻煩,所以我們可以先做好一個Credential參數值直接登入,當然這是有風險的,因為你的密碼直接嵌入腳本里面:
$username = "用戶名"
$password = ConvertTo-SecureString "你的密碼" -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential($username, $password)
# 然后在 -Credential 參數中使用 $credential 變量
Enter-PSSession -ComputerName "遠程計算機名或IP" -Credential $credential
常見遠程處理技術
認證方式
此參數在復雜網絡環境中至關重要。以下是幾種常見機制的對比:
實際案例
1.連接到非標準端口并使用 SSL
假設目標服務器 ServerA 的 WinRM HTTPS 監聽在端口 9999,并且你信任其自簽名證書(通過 -SessionOption 跳過部分檢查)。
# 創建一個跳過CA檢查和CN檢查的會話選項(測試環境常用,生產環境請使用有效證書)
$so = New-PSSessionOption -SkipCACheck -SkipCNCheck
# 建立交互式會話
Enter-PSSession -ComputerName ServerA -Port 9999 -UseSSL -SessionOption $so -Credential (Get-Credential)
2.在工作組環境中使用特定認證方式
你的計算機和工作組中的計算機 192.168.1.100 都需要已配置 WinRM
# 1. 先將目標IP添加到本地TrustedHosts(信任所有主機,僅供參考,請注意安全風險)
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "192.168.1.100" -Force
# 2. 使用Basic認證并連接(必須配合SSL)
$cred = Get-Credential # 輸入192.168.1.100上的本地用戶名和密碼
Invoke-Command -ComputerName 192.168.1.100 -UseSSL -Authentication Basic -Credential $cred -ScriptBlock { Get-Service WinRM } -Port 5986
3.使用 CredSSP 實現雙跳認證
CredSSP 將憑據緩存在遠程服務器,使用 CredSSP 會使你面臨潛在的憑據盜竊攻擊。 如果遠程計算機被攻破,攻擊者將有權訪問用戶的憑據。 默認情況下,CredSSP 在客戶端和服務器計算機上都處于禁用狀態。 應該僅在最受信任的環境中啟用 CredSSP。 例如,連接到域控制器的域管理員可能已啟用 CredSSP,因為域控制器是高度可信任的。
假設你從本地客戶端需要先登錄到跳板機 JumpServer,然后從跳板機訪問另一臺內部服務器 AppServer 上的資源。
在跳板機 (JumpServer) 上啟用 CredSSP 服務端(以管理員身份運行):
Enable-WSManCredSSP -Role Server
在你的本地客戶端上啟用 CredSSP 客戶端并指定委托:(以管理員身份運行)
Enable-WSManCredSSP -Role Client -DelegateComputer "JumpServer"
建立到跳板機的會話并使用 CredSSP:
$cred = Get-Credential
$session = New-PSSession -ComputerName JumpServer -Credential $cred -Authentication CredSSP
Invoke-Command -Session $session -ScriptBlock {
# 現在可以從 JumpServer 訪問 AppServer 上的資源了
Get-Item \\AppServer\C$\SomeFile.txt
}
Remove-PSSession $session
4.連接到 32 位 PowerShell 端點
在某些需要兼容舊版32位應用程序或腳本的場景下,可能需要連接到此端點
Invoke-Command -ComputerName LegacyServer -ConfigurationName "microsoft.powershell32" -ScriptBlock {
# 這里運行在32位環境中
[Environment]::Is64BitProcess # 會返回 False
}
5.基于資源的 Kerberos 約束委派
從 Windows Server 2012 開始,可以放棄使用 CredSSP,而改為使用約束委派。 約束委派通過使用安全描述符而不是服務器名稱允許列表來實現服務票證的委派。 這允許資源確定哪些安全主體可以代表另一個用戶請求票證。 無論域的功能級別如何,基于資源的約束委派都能正確工作。
約束委派需要:
- 訪問與運行 Windows PowerShell 遠程處理命令的主機計算機位于同一域中的域控制器。
- 訪問托管你嘗試從中間遠程服務器訪問的遠程服務器的域中的域控制器。
設置權限的代碼需要一臺使用 Active Directory PowerShell 遠程服務器管理工具 (RSAT) 運行 Windows Server 的計算機。 可通過運行以下兩個命令,將 RSAT 添加為 Windows 功能:
Add-WindowsFeature RSAT-AD-PowerShell
Import-Module ActiveDirectory
要將基于資源的 Kerberos 約束委派從 LON-SVR1 授予到 LON-SVR2,然后再到 LON-SVR3,請運行以下命令:
Set-ADComputer -Identity LON-SVR2 -PrincipalsAllowedToDelegateToAccount LON-SVR3
有一個問題可能導致此命令失敗。 密鑰發行中心 (KDC) 有 15 分鐘的 SPN 負緩存。 如果 LON-SVR2 已嘗試與 LON-SVR3 通信,則存在一個負緩存條目。 需要使用以下方法之一來清除 LON-SVR2 上的緩存:
- 運行命令
klist purge -li 0x3e7。 這是首選方法,也是最快的方法。 - 等待 15 分鐘,使緩存自動清除。
- 重啟 LON-SVR2。
要測試約束委派,請運行以下代碼示例:
$cred = Get-Credential Adatum\TestUser
Invoke-Command -ComputerName LON-SVR1.Name -Credential $cred -ScriptBlock {Test-Path \\$($using:ServerC.Name)\C$ Get-Process lsass -ComputerName $($using:LON-SVR2.Name)
Get-EventLog -LogName System -Newest 3 -ComputerName $using:LON-SVR3.Name
}
6.Just Enough Administration
這種技術比較高級,暫時還handle不了,略過。感興趣可以看下圖官網解釋:

會話控制
New-PSSessionOption 創建的會話選項對象可以精細控制會話行為,并通過 -SessionOption 參數傳遞給命令
# 創建一個會話選項,調整各種超時設置并跳過證書檢查(測試用)
$options = New-PSSessionOption -IdleTimeout (60 * 60 * 1000) ` # 空閑超時1小時(單位毫秒)
-OperationTimeout (5 * 60 * 1000) ` # 操作超時5分鐘
-OpenTimeout (2 * 60 * 1000) ` # 打開連接超時2分鐘
-SkipCACheck ` # 跳過CA檢查(測試環境自簽名證書時)
-SkipCNCheck # 跳過CN檢查(測試環境證書名稱不匹配時)
# 在Invoke-Command中使用此會話選項
Invoke-Command -ComputerName SecureServer -UseSSL -SessionOption $options -ScriptBlock { Get-Process }
重要提醒: -SkipCACheck 和 -SkipCNCheck 會降低連接的安全性,僅建議在測試環境或受信任的隔離網絡中使用。生產環境應部署有效的、由受信任CA簽發的證書,并確保證書名稱與主機名匹配。
參數發送到遠程計算機
以下命令的意圖是列出每臺目標計算機上 10 條最近的安全事件日志項。 但此命令將不會按編寫的那樣起作用:
$Log = 'Security'
$Quantity = 10
Invoke-Command –Computer ONE,TWO –ScriptBlock {
Get-EventLog –LogName $Log –Newest $Quantity
}
原因在于變量 $Log 和 $Quantity 僅在本地計算機上有意義,在將這些值發送到遠程計算機之前,這些值不會插入到腳本塊中。 因此,遠程計算機不能理解這些值。
此命令的正確語法如下所示:
$Log = 'Security'
$Quantity = 10
Invoke-Command –Computer ONE,TWO –ScriptBlock {
Param($x,$y) Get-EventLog –LogName $x –Newest $y
} –ArgumentList $Log,$Quantity
通過此語法,局部變量將傳遞給 Invoke-Command 的 ArgumentList 參數。 在腳本塊中,創建了一個 Param() 塊,其中包含與 –ArgumentList 值列表相同數量的變量,在本例中為兩個。
Windows PowerShell 3.0 引入了簡化的替代方法。 如果有一個局部變量 $variable,并且希望將其內容包含在將在遠程計算機上運行的命令中,可運行以下語法:
Invoke-Command –ScriptBlock { Do-Something $Using:variable } –ComputerName REMOTE
$Using: 前綴經本地和遠程計算機正確處理,從而讓 $Using:variable 被局部變量 $variable 的內容替換。
更多范圍可以回顧:函數與模塊變量的變量范圍里查看
會話管理與遠程計算機的持久連接
每臺計算機都有一個名為 WSMan 的驅動器,其中包含許多與會話相關的配置參數,例如:
- 最大會話運行時
- 最長空閑時間
- 最大傳入連接數
- 每個管理員的最大會話數
可運行dir WSMan:\localhost\shell來瀏覽這些配置參數,并在同一位置更改它們。 還可以通過組策略控制許多設置。
創建和管理持久 PSSession
以下命令在 Server01 和 Server02 上創建遠程會話,而會話對象將存儲在 變量中$s:
$s = New-PSSession -ComputerName Server01, Server02
建立會話后,你可以在這些會話中運行任何命令。 此外,由于會話是持久的,因此你可以從一個命令收集數據,并在另一個命令中使用它。
接著你可以統一管理不同session
例如,下面的命令在 變量中的會話中運行 Get-HotFix 命令,并將結果保存在 $s 變量中$h:
Invoke-Command -Session $s {$h = Get-HotFix}
這些個session中都存了一個叫$h的變量,所以后續操作依舊可以操作$h
Invoke-Command -Session $s {$h | where {$_.InstalledBy -ne "NTAUTHORITY\SYSTEM"}}
斷開連接
如你所了解,當啟動計算機和遠程計算機都運行 Windows PowerShell 3.0 及更高版本時,可以斷開與 PSSession 的連接。 斷開連接通常需要手動進行。 在某些情況下,如果連接中斷,Windows PowerShell 會自動將連接置于“斷開連接”狀態。 但是,如果手動關閉 Windows PowerShell 主機應用程序,則其不會斷開與會話的連接,而只是將會話關閉。
| 命令 | 作用 | 會話是否還存在遠程機上? | 使用場景 |
|---|---|---|---|
Exit-PSSession |
退出交互模式,返回本地 | ? 存在 | 相當于“掛起對話”,但不銷毀 |
Disconnect-PSSession |
斷開連接,保留遠程會話 | ? 存在 | 想留著會話,稍后從本地或其他機器再連上 |
Remove-PSSession |
銷毀遠程會話 | ? 不存在 | 完全結束,不再保留 |
斷開會話
Disconnect-PSSession -Session $session
會話不會銷毀,只是把連接切斷。
重新連接
Connect-PSSession -ComputerName Server01 -Name <會話名>
或者如果你已經有 $session 對象(比如導出來保存過),也可以直接:
Connect-PSSession -Session $session
- 斷開 ≠ 關閉
Disconnect-PSSession:會話還在遠程機上保持。Remove-PSSession:才是真的銷毀。
- 自動斷開
- 如果網絡掉線、遠程機重啟,PowerShell 可能自動把狀態變成
Disconnected。 - 但是如果你直接關掉 PowerShell 窗口,會話就直接被關閉了(不會留在遠程機)。
- 如果網絡掉線、遠程機重啟,PowerShell 可能自動把狀態變成
- 限制
- 只能 reconnect 自己的會話,不能接管別人開的。
- 需要 Windows PowerShell 3.0+。
本文來自博客園,作者:竹等寒,轉載請注明原文鏈接。

浙公網安備 33010602011771號