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 cmdlet帮助识别会话对象类型:

$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 cmdlet创建一个凭据对象,以在创建会话时指定替代凭据:

$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/