PowerShell 可重複使用工作階段:持久遠端連線指南

管理遠端系統可能會迅速變得令人頭痛,尤其是在不同機器上執行多個命令時。反覆重新連接到系統不僅浪費時間,還會拖慢工作流程。聽起來熟悉嗎?別擔心,還有更好的方法!

在本指南中,您將學會如何使用可重用的 PowerShell 遠端會話,使管理遠端系統更快、更簡單且更高效。

準備好提升您的 PowerShell 遠端技能了嗎?讓我們開始吧!

創建和使用會話

在處理遠端系統時,最繁瑣的任務之一就是每次執行命令時都要重新連接。在這種情況下,可重用的會話就派上用場了。

創建持久會話可保持持續連接。這樣做可以消除在重複執行多個命令時連接和斷開的需要。

首先,您需要創建一個可重用的會話。

New-PSSession cmdlet 建立到遠端計算機的持久連接:

$session = New-PSSession -ComputerName SRV2

這個會話對象可以傳遞給像 Invoke-Command 這樣的命令,讓您在整個腳本中重用同一會話。

例如,您可以通過執行基本命令來測試連接:

Invoke-Command -Session $session -ScriptBlock { hostname }

可重用的會話還允許您在遠端系統上存儲和檢索變數:

Invoke-Command -Session $session -ScriptBlock { $foo = 'Please be here next time' }
Invoke-Command -Session $session -ScriptBlock { $foo }

這種持久存儲能力是可重用會話的一個重要優勢,使您能夠在多個命令之間保持狀態。

調整函數以便於遠端使用

讓我們將庫存功能調整為支援可重複使用的工作階段。

首先,我們添加一個Session參數來接受一個工作階段物件,其中Get-Member命令協助識別工作階段物件的類型:

$session | Get-Member

在確定工作階段物件為System.Management.Automation.Runspaces.PSSession類型後,下一步是定義Get-WmiObjectValue功能。

此功能使用工作階段參數以啟用遠端執行,從而運行在遠端系統上的指令區塊並檢索特定的WMI屬性。

function Get-WmiObjectValue {
    [CmdletBinding()]
    param(
        # Specify the name of the WMI property to query
        [Parameter(Mandatory)]
        [string]$PropertyName,

        # Specify the name of the WMI class to query
        [Parameter(Mandatory)]
        [string]$WmiClassName,

        # Specify the remote session object to use for invoking the command
        [Parameter(Mandatory)]
        [System.Management.Automation.Runspaces.PSSession]$Session
    )

    # Define the script block to execute on the remote machine
    $scriptBlock = {
        # Get the sum of the specified property from the WMI class
        $number = (Get-CimInstance -ClassName $using:WmiClassName | Measure-Object -Property $using:PropertyName -Sum).Sum

        # Convert the sum to gigabytes
        $numberGb = $number / 1GB

        # Round the result to 2 decimal places
        [math]::Round($numberGb, 2)
    }

    # Execute the script block on the remote machine using the provided session
    Invoke-Command -Session $Session -Scriptblock $scriptBlock
}

讓我們試用這個功能並看看會發生什麼。

Get-WmiObjectValue -PropertyName Capacity -WmiClassName Win32_PhysicalMemory -Session $session

您可能會在某些時候遇到這個錯誤。但請不用擔心。繼續閱讀,您將學會如何解決這個錯誤。

解決驗證問題

如果遇到“拒絕存取”錯誤,很可能是因為權限不足。預設情況下,可重複使用的工作階段會繼承用於建立它們的憑證。

檢查目前已驗證的使用者在系統上的使用者名稱:

whoami

如果稱為使用者的網域使用者沒有權限在遠端電腦上查詢WMI,將Invoke-Command提升為使用管理員帳戶。

首先,使用Get-Credential命令來創建一個憑證物件,以指定在建立工作階段時使用替代憑證:

$adminCred = Get-Credential -UserName adam

驗證後,測試工作階段:

Invoke-Command -Session $session -Scriptblock {hostname} -Credential $adminCred

這個測試確保工作階段如預期般運作,然後再執行您的庫存功能。

但如果會話不起作用,則已使用不正確的憑證創建。如果是這樣,您必須刪除當前的會話:

Remove-PSSession -Session $session

Remove-PSSession cmdlet 可以在本地和遠程計算機上刪除會話。

刪除舊會話後,創建另一個新會話。但這次,將會話作為管理員用戶進行身份驗證:

$session = New-PSSession -ComputerName SRV2 -Credential $adminCred

再次嘗試使用新會話進行 Invoke-Command,看看發生了什麼。

Invoke-Command -Session $session -Scriptblock {hostname} -Credential $adminCred

現在您確信新會話有效,讓我們再試一次這個功能。

Get-WmiObjectValue -PropertyName Capacity -WmiClassName Win32_PhysicalMemory -Session $session

將所有內容整合在一起

辛苦工作已經結束,現在是將所有內容組合到一個腳本中的時候。

這個最終腳本將收集庫存信息,顯示結果並清理會話:

function Get-WmiObjectValue {
    [CmdletBinding()]
    param(
        # Specify the name of the WMI property to query
        [Parameter(Mandatory)]
        [string]$PropertyName,

        # Specify the name of the WMI class to query
        [Parameter(Mandatory)]
        [string]$WmiClassName,

        # Specify the remote session object to use for invoking the command
        [Parameter(Mandatory)]
        [System.Management.Automation.Runspaces.PSSession]$Session
    )

    # Define the script block to execute on the remote machine
    $scriptBlock = {
        # Get the sum of the specified property from the WMI class
        $number = (Get-CimInstance -ClassName $using:WmiClassName | Measure-Object -Property $using:PropertyName -Sum).Sum

        # Convert the sum to gigabytes
        $numberGb = $number / 1GB

        # Round the result to 2 decimal places
        [math]::Round($numberGb, 2)
    }

    # Execute the script block on the remote machine using the provided session
    Invoke-Command -Session $Session -Scriptblock $scriptBlock
}

## Grab the alternate credential: Get-CimInstance will work on the remote computer
$adminCred = Get-Credential -UserName adam

## Create a session authenticating as the adam (admin) user
$session = New-PSSession -ComputerName SRV2 -Credential $adminCred

## Find the total memory and total volume storage space on the remote computer
$totalMemoryGb = Get-WmiObjectValue -PropertyName Capacity -WmiClassName Win32_PhysicalMemory -Session $session
$totalStorageGb = Get-WmiObjectValue -PropertyName FreeSpace -WmiClassName Win32_LogicalDisk -Session $session

Write-Host "The computer $($session.ComputerName) has $totalMemoryGb GB of memory and $totalStorageGb GB of free space across all volumes."

## Remove the shared session
Remove-PSSession -Session $session

保存並執行腳本(Get-InventoryInfo.ps1)以驗證其按照預期運行。

結論

在本教程中,您學會了構建一個強大的功能,該功能使用可重複使用的會話有效地管理遠程計算機。您現在知道如何在多個命令之間保持持久連接,並在遠程系統上執行復雜任務而無需每次斷開連接。

往前看,您可以通過將可重複使用的會話納入更大的自動化工作流程來擴展這些知識。一個例子是擴展庫存功能以收集額外的系統指標或自動執行多個遠程計算機上的維護任務。

將可重複使用的工作階段與其他 PowerShell 功能結合。優化您的 IT 管理和自動化工作,節省時間並減少手動干預。

Source:
https://adamtheautomator.com/powershell-reusable-sessions/