Recientemente he tenido que hacer limpieza
de restos debido a la baja de un compañero administrador. Unos días después, mi
script de chequeo de logs todavía me cantaba errores que podían estar relacionados
con el uso de su cuenta de administrador. Lo mas probable es que hubiera
sesiones remotas abiertas con su usuario (ya deshabilitado), desperdigadas por
los servidores de la compañía. Para buscarlas, hay varias formas de hacerlo. A continuación,
os muestro dos de ellas.
THE OLD WAY, usar los comandos quser y
logout
Primero necesitamos ver que usuarios están logados
en el servidor remoto y con que id de sesión para después, poder hacerles logof
remotamente. Para ello, usaremos el comando quser de la siguiente forma:
Quser /server:servername
Este
comando devuelve la lista de usuarios logados en un equipo remoto, indicando el
nombre, el id de la sesión, el estado y los tiempos de logon y de inactividad. Una
vez que tengamos todos esos datos, podremos decidir a qué sesiones queremos
cerrar y cuáles no. De las sesiones que queramos cerrar, apuntaremos su id de sesión
y lo utilizaremos con el comando logoff de la siguiente forma:
Logoff sesionID
/SERVER:servername [/V]
THE COOL NEW WAY, usar
powershell
Porque si, porque powershell es cool y
nosotros queremos ser cool, ¿verdad? El problema de usar powershell, es que no
hay una forma estándar de comprobar que usuarios hay logados en una maquina
remota. Si, siempre podemos invocar quser desde powershell, ¿pero de verdad
quieres pelearte parseando el texto de la salida? Personalmente prefiero usar
otra técnica. Simplemente busco procesos “explorer.exe” (se crea uno por cada sesión
local o remota que haya) y extraigo el nombre del usuario al que pertenece el
proceso. Si, no muestra información del estado de la sesión, ni de la hora de
inicio ni de cuanto tiempo lleva inactiva… Pero me vale para meterlo en un
objeto y hacer algo muy muy Cool después. Pero primero vamos a echarle un
vistazo a la función que utilizo:
function Get-LoggedOnUser
{
[CmdletBinding()]
param
(
[Parameter(ValueFromPipeline)]
[ValidateScript({Test-Connection -ComputerName $_.dnshostname -Quiet -Count 1})]
[ValidateNotNullOrEmpty()]
[Microsoft.ActiveDirectory.Management.ADComputer[]]$Computer
)
process{
$output = @()
$explorerprocesses = @(Get-WmiObject -ComputerName $Computer.DNSHostName -Query "Select * FROM Win32_Process WHERE Name='explorer.exe'" -ErrorAction SilentlyContinue)
foreach($process in $explorerprocesses){
$myObject = New-Object PSCustomObject
$myObject | Add-Member -type NoteProperty -name ComputerName -Value ($Computer.DNSHostName)
$myObject | Add-Member -type NoteProperty -name SessionUser -Value ($process.getowner().user)
$myObject | Add-Member -type NoteProperty -name SessionUserDomain -Value ($process.getowner().domain)
$myObject | Add-Member -type NoteProperty -name SessionId -Value ($process.sessionId)
$output += $myObject
}
Return $output
}
}
Como podéis ver, el código de esta función acepta
objetos de tipo ADComputer a través del pipe y devuelve un objeto personalizado
con la información de las sesiones de usuario abierta usando los procesos explorer.exe
para ello.
Esto nos permite hacer búsquedas de equipos
en AD con el cmdlet get-adcomputer y redirigir la salida a nuestra funcion.
Una vez que hemos hecho esto, pues ya
podemos meterle el código que queramos al objeto devuelto, bien usando logoff,
con una pssession, o lo que queramos. Por ejemplo:
Get-ADComputer -Filter 'OperatingSystem -like "Windows Server*"' | Get-LoggedOnUser
Comentarios
Publicar un comentario