1

最小问题:

执行以下操作后,如何正确处理遗留的远程会话连接:

$session = New-PSSession -ComputerName $VM -Credential $CurrentUser
Invoke-Command -Session $session -ScriptBlock {
    $drive = New-PSDrive -Credential $Using:CurrentUser "dummyDriveName" -Root (Split-Path $Using:TargetPath) -PSProvider "FileSystem" 
    Set-Location $Using:TargetPath
}

Invoke-Command -Session $session -ScriptBlock {
    Remove-PSDrive "dummyDriveName"
}
Remove-PSSession -Session $session

我正在运行的代码大致如下所示:

$VMs = @(
    "vm1.foo.lan",
    "vm2.foo.lan",
    "vm3.foo.lan"
)

$TargetPath = "\\$env:ComputerName\bar\bin\Debug"

$CurrentUser = (Get-Credential -Credential $env:UserName)
[System.Management.Automation.Runspaces.PSSession[]]$Sessions = @()

foreach ($VM in $VMs) {
    $session = New-PSSession -ComputerName $VM -Credential $CurrentUser
    $Sessions = $Sessions + $session

    Invoke-Command -Session $session -ScriptBlock {
        $drive = New-PSDrive -Credential $Using:CurrentUser "dummyDriveName" -Root (Split-Path $Using:TargetPath) -PSProvider "FileSystem" 
        Set-Location $Using:TargetPath
        #Actually do something here, but it's not relevant ... I can reproduce with this line commented out.
    }
}

# Wait until Target.exe are known to be complete.

foreach ($session in $Sessions) {
    Invoke-Command -Session $session -ScriptBlock {
        Remove-PSDrive "dummyDriveName"
    }
    Remove-PSSession -Session $session
}

我的意图是让一组远程机器都调用exe我机器上的一个坐席,通过远程共享公开。

从广义上讲,我:

  • 以我自己的身份连接到远程机器。
  • 捕捉这种联系。
  • 设置一个连接到我的远程驱动器
    • (这是避免双跳问题所必需的,而无需求助CredSsp参见:https ://docs.microsoft.com/en-us/powershell/scripting/setup/ps-remoting-second-hop )
  • 做一些事情
  • 对所有机器重复此操作。
  • 等到远程进程完成。
  • 重新连接到所有机器以删除驱动器和连接会话。

在这结束时,我仍然有: 在此处输入图像描述

这些会话最终似乎会衰减,但并不可靠,并且它能够使允许的最大会话数饱和,从而导致错误说:

No more connections can be made to this remote computer at this time because there are already as many connections as the computer can accept
+ CategoryInfo          : InvalidOperation: (dummy:PSDriveInfo) [New-PSDrive], Win32Exception
+ FullyQualifiedErrorId : CouldNotMapNetworkDrive,Microsoft.PowerShell.Commands.NewPSDriveCommand
+ PSComputerName        : build7.foo.lan

更新:

感谢@jrider 的建议Get-SmbSession。在我的脚本的其余部分返回之后运行它:

PS C:\WorkingDirectoty> Get-SmbSession

SessionId    ClientComputerName ClientUserName NumOpens
---------    ------------------ -------------- --------
773228331225 10.xxx.yyy.89       FOO\MDM        785
773228331233 10.xxx.yyy.60       FOO\MDM        637
773228331245 10.xxx.yyy.89       FOO\MDM        239
773228331253 10.xxx.yyy.54       FOO\MDM        136
773228331261 10.xxx.yyy.54       FOO\MDM        882
773228331269 10.xxx.yyy.60       FOO\MDM        389

我显然不希望这个脚本盲目地关闭每个会话,无论它是否与这个脚本相关,所以我想我想将我的会话映射到 IP 地址并关闭任何具有该 IP 地址的东西?有没有人 JustKnow 必要的 PowerShell 咒语来实现这一目标?

4

2 回答 2

2

按计算机名称关闭 SMB 会话(已更新以包括 Brondhl 的建议):

$vmName = $env:ComputerName
$IP =  [System.Net.Dns]::GetHostAddresses($vmName).IPAddressToString
Get-SmbSession | Where-Object {$_.ClientComputerName -eq $IP} | Close-SmbSession -Force
于 2018-04-26T20:17:40.877 回答
1

作为最终参考,我的完整清理代码如下所示:

foreach ($session in $Sessions) {
    Write-Host ""
    $vmName = $session.ComputerName
    $vmIPAddress = [System.Net.Dns]::GetHostAddresses($vmName).IPAddressToString

    Write-Host "*** Killing any active Target.exe processes on $vmName ***"
    Invoke-Command -Session $session -ScriptBlock {
        Stop-Process -Name "Target" -Force
    }

    Write-Host "*** Disconnecting the remote Drive created to give $vmName easy access to $RepositoryShare***"
    Invoke-Command -Session $session -ScriptBlock {
        Remove-PSDrive "dummyDriveName" 
    }

    Write-Host "*** Closing any open PS connections to $vmName ***"
    Remove-PSSession -Session $session

    Write-Host "*** Closing the still-open Windows Share connection from $vmName to $env.ComputerName ***"
    Get-SmbSession | Where-Object {$_.ClientComputerName -eq $vmIPAddress} | Close-SmbSession -Force
}
于 2018-04-26T20:29:10.433 回答