PowerShell
Powershell Remoting
Buscar..
Observaciones
Habilitando el control remoto de PowerShell
El control remoto de PowerShell primero debe estar habilitado en el servidor al que desea conectarse de forma remota.
Enable-PSRemoting -Force
Este comando hace lo siguiente:
- Ejecuta el cmdlet Set-WSManQuickConfig, que realiza las siguientes tareas:
- Inicia el servicio WinRM.
- Establece el tipo de inicio en el servicio WinRM en Automático.
- Crea una escucha para aceptar solicitudes en cualquier dirección IP, si no existe una.
- Habilita una excepción de cortafuegos para comunicaciones WS-Management.
- Registra las configuraciones de sesión de Microsoft.PowerShell y Microsoft.PowerShell.Workflow, si aún no están registradas.
- Registra la configuración de la sesión de Microsoft.PowerShell32 en computadoras de 64 bits, si aún no está registrada.
- Habilita todas las configuraciones de sesión.
- Cambia el descriptor de seguridad de todas las configuraciones de sesión para permitir el acceso remoto.
- Reinicia el servicio WinRM para hacer efectivos los cambios anteriores.
Solo para entornos sin dominio
Para los servidores en un dominio de AD, la autenticación remota de PS se realiza a través de Kerberos ('Predeterminado'), o NTLM ('Negociar'). Si desea permitir la comunicación remota a un servidor que no sea de dominio, tiene dos opciones.
Configure la comunicación WSMan a través de HTTPS (que requiere la generación de certificados) o habilite la autenticación básica que envía sus credenciales a través del código codificado en base64 (básicamente es lo mismo que texto sin formato, así que tenga cuidado).
En cualquier caso, deberá agregar los sistemas remotos a su lista de hosts de confianza de WSMan.
Habilitar la autenticación básica
Set-Item WSMan:\localhost\Service\AllowUnencrypted $true
A continuación, en el equipo que desee conectar, usted debe indicarle a confiar en el equipo que se está conectando.
Set-Item WSMan:\localhost\Client\TrustedHosts '192.168.1.1,192.168.1.2'
Set-Item WSMan:\localhost\Client\TrustedHosts *.contoso.com
Set-Item WSMan:\localhost\Client\TrustedHosts *
Importante : debe decirle a su cliente que confíe en la computadora direccionada de la manera en que desea conectarse (por ejemplo, si se conecta a través de IP, debe confiar en la IP, no en el nombre de host)
Conexión a un servidor remoto a través de PowerShell
Usando credenciales de su computadora local:
Enter-PSSession 192.168.1.1
Pedir credenciales en la computadora remota
Enter-PSSession 192.168.1.1 -Credential $(Get-Credential)
Ejecutar comandos en una computadora remota
Una vez que Powershell remoting esté habilitado (Enable-PSRemoting), puede ejecutar comandos en la computadora remota de esta manera:
Invoke-Command -ComputerName "RemoteComputerName" -ScriptBlock {
Write host "Remote Computer Name: $ENV:ComputerName"
}
El método anterior crea una sesión temporal y la cierra justo después de que finalice el comando o scriptblock.
Para dejar la sesión abierta y ejecutar otro comando más adelante, primero debe crear una sesión remota:
$Session = New-PSSession -ComputerName "RemoteComputerName"
Luego, puede usar esta sesión cada vez que invoque comandos en la computadora remota:
Invoke-Command -Session $Session -ScriptBlock {
Write host "Remote Computer Name: $ENV:ComputerName"
}
Invoke-Command -Session $Session -ScriptBlock {
Get-Date
}
Si necesita usar diferentes credenciales, puede agregarlas con el parámetro -Credential
:
$Cred = Get-Credential
Invoke-Command -Session $Session -Credential $Cred -ScriptBlock {...}
Advertencia de serialización remota
Nota:
Es importante saber que el control remoto serializa los objetos de PowerShell en el sistema remoto y los deserializa al final de la sesión remota, es decir, se convierten a XML durante el transporte y pierden todos sus métodos.
$output = Invoke-Command -Session $Session -ScriptBlock {
Get-WmiObject -Class win32_printer
}
$output | Get-Member -MemberType Method
TypeName: Deserialized.System.Management.ManagementObject#root\cimv2\Win32_Printer
Name MemberType Definition
---- ---------- ----------
GetType Method type GetType()
ToString Method string ToString(), string ToString(string format, System.IFormatProvi...
Mientras que tienes los métodos en el objeto PS normal:
Get-WmiObject -Class win32_printer | Get-Member -MemberType Method
TypeName: System.Management.ManagementObject#root\cimv2\Win32_Printer
Name MemberType Definition
---- ---------- ----------
CancelAllJobs Method System.Management.ManagementBaseObject CancelAllJobs()
GetSecurityDescriptor Method System.Management.ManagementBaseObject GetSecurityDescriptor()
Pause Method System.Management.ManagementBaseObject Pause()
PrintTestPage Method System.Management.ManagementBaseObject PrintTestPage()
RenamePrinter Method System.Management.ManagementBaseObject RenamePrinter(System.String NewPrinterName)
Reset Method System.Management.ManagementBaseObject Reset()
Resume Method System.Management.ManagementBaseObject Resume()
SetDefaultPrinter Method System.Management.ManagementBaseObject SetDefaultPrinter()
SetPowerState Method System.Management.ManagementBaseObject SetPowerState(System.UInt16 PowerState, System.String Time)
SetSecurityDescriptor Method System.Management.ManagementBaseObject SetSecurityDescriptor(System.Management.ManagementObject#Win32_SecurityDescriptor Descriptor)
Uso del argumento
Para usar los argumentos como parámetros para el bloque de secuencias de comandos remotos, uno puede usar el parámetro ArgumentList
de Invoke-Command
o la sintaxis de $Using:
.
Usando ArgumentList
con parámetros sin nombre (es decir, en el orden en que se pasan al bloque de secuencias de comandos):
$servicesToShow = "service1"
$fileName = "C:\temp\servicestatus.csv"
Invoke-Command -Session $session -ArgumentList $servicesToShow,$fileName -ScriptBlock {
Write-Host "Calling script block remotely with $($Args.Count)"
Get-Service -Name $args[0]
Remove-Item -Path $args[1] -ErrorAction SilentlyContinue -Force
}
Usando ArgumentList
con parámetros nombrados:
$servicesToShow = "service1"
$fileName = "C:\temp\servicestatus.csv"
Invoke-Command -Session $session -ArgumentList $servicesToShow,$fileName -ScriptBlock {
Param($serviceToShowInRemoteSession,$fileToDelete)
Write-Host "Calling script block remotely with $($Args.Count)"
Get-Service -Name $serviceToShowInRemoteSession
Remove-Item -Path $fileToDelete -ErrorAction SilentlyContinue -Force
}
Utilizando $Using:
sintaxis:
$servicesToShow = "service1"
$fileName = "C:\temp\servicestatus.csv"
Invoke-Command -Session $session -ScriptBlock {
Get-Service $Using:servicesToShow
Remove-Item -Path $fileName -ErrorAction SilentlyContinue -Force
}
Una buena práctica para la limpieza automática de PSSessions
Cuando se crea una sesión remota a través del cmdlet New-PSsession
, la PSSession continúa hasta que finaliza la sesión actual de PowerShell. Lo que significa que, de forma predeterminada, la PSSession
y todos los recursos asociados se seguirán utilizando hasta que finalice la sesión actual de PowerShell.
Múltiples PSSessions
activas pueden convertirse en una carga para los recursos, en particular para los scripts de larga ejecución o interconectados que crean cientos de PSSessions
en una sola sesión de PowerShell.
Es una buena práctica eliminar explícitamente cada PSSession
después de que se termine de usar. [1]
La siguiente plantilla de código utiliza try-catch-finally
para lograr lo anterior, combinando el manejo de errores con una forma segura de asegurar que todas las PSSessions
creadas se eliminen cuando se terminen de usar:
try
{
$session = New-PSsession -Computername "RemoteMachineName"
Invoke-Command -Session $session -ScriptBlock {write-host "This is running on $ENV:ComputerName"}
}
catch
{
Write-Output "ERROR: $_"
}
finally
{
if ($session)
{
Remove-PSSession $session
}
}
Referencias: [1] https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.core/new-pssession