Como fechar sessões do PowerShell órfãs?

5

Eu estava criando um script que usa vários 'Invoke-Command -asjob' em um servidor remoto, apesar de que, ao testar um While-Loop, fiquei bravo e tive que pará-lo. No entanto, quando eu agora tento um comando Invoke-Command no servidor de destino, ele retorna o trabalho com falha no estado. Quando eu recebo o trabalho, ele retorna com este erro:

The WS-Management service cannot process the request. This user has exceeded the maximum number of concurrent shells allowed for this plugin. Close at least one open shell or raise the plugin quota for this user.
+ FullyQualifiedErrorId : -2144108060,PSSessionStateBroken

Quando faço o Get-PSSession, nenhum deles está listado, por isso não posso usar o Remove-PSSession (esta é a única sugestão do Google até agora).

Isso é basicamente o que é executado:

While ($True)
    { 
    Invoke-Command -Computername $RemoteServer -AsJob {Get-ChildItem}
    }

Eu comecei e fiz o Get-Job | Remove-Job, que removeu todos os trabalhos, mas ainda não consigo iniciar um Invoke-Command -AsJob no servidor remoto.

Eu também reiniciei o Serviço WSMAN no servidor remoto (fazendo logon nele com o RDP), o que não funcionou.

    
por SuHwak 06.12.2016 / 14:11

2 respostas

4

Os trabalhos remotos seriam executados em um processo wsmprovhost.exe por trabalho. Você deve conseguir a força bruta finalizar esses processos com o WMI - ou mesmo remotamente reinicializar a máquina. Você corre o risco de matar empregos hospedados para outros usuários / atividades, é claro.

Isso encerraria todos os processos wsmprovhost.exe no computador chamado (ou matriz de nomes de computador):

(gwmi win32_process -ComputerName $RemoteServer) |? 
    { $_.Name -imatch "wsmprovhost.exe" } |% 
    { $_.Name; $_.Terminate() }
    
por 13.12.2016 / 20:17
0

Eu sei que este post é meio antigo. O @Matthew Wetmore tem uma ótima solução para remover ALL PSSessions de um servidor remoto. Mas, @SuHwak tinha uma pergunta sobre como parar apenas sessões que um usuário específico gerou.

Para esse fim, escrevi uma função para ajudar.

function Get-PSSessionsForUser
{
    param(
        [string]$ServerName,
        [string]$UserName
    )

    begin {
        if(($UserName -eq $null) -or ($UserName -eq ""))
        { $UserName = [Environment]::UserName }
        if(($ServerName -eq $null) -or ($ServerName -eq ""))
        { $ServerName = [Environment]::MachineName }
    }

    process {
        Get-CimInstance  -ClassName Win32_Process -ComputerName $ServerName | Where-Object { 
            $_.Name -imatch "wsmprovhost.exe"
        } | Where-Object {
            $UserName -eq (Invoke-CimMethod -InputObject $_ -MethodName GetOwner).User
        }
    }
}

E, para usá-lo ...

#Get, but do not terminate sessions for the current user, on the local computer.
Get-PSSessionsForUser

#Terminate all sessions for for the current user, on the local computer.
(Get-PSSessionsForUser) | Invoke-CimMethod -MethodName Terminate

<####################################>

#Get, but do not terminate sessions for a specific user, on the local computer.
Get-PSSessionsForUser -UserName "custom_username"

#Terminate all sessions for a specific user, on the local computer.
(Get-PSSessionsForUser -UserName "custom_username") | Invoke-CimMethod -MethodName Terminate

<####################################>

#Get, but do not terminate sessions for the current user, on a remote server.
Get-PSSessionsForUser -ServerName "remote_server"

#Terminate all sessions for the current user, on a remote server.
(Get-PSSessionsForUser -ServerName "remote_server") | Invoke-CimMethod -MethodName Terminate

<####################################>

#Get, but do not terminate sessions for a specific user, on a remote server.
Get-PSSessionsForUser -UserName "custom_username" -ServerName "remote_server"

#Terminate all sessions for a specific user, on a remote server.
(Get-PSSessionsForUser -UserName "custom_username" -ServerName "remote_server") | Invoke-CimMethod -MethodName Terminate
    
por 31.10.2018 / 13:50

Tags