Si alguna vez has intentado ejecutar comandos remotos en PowerShell y te has encontrado con obstáculos, probablemente seas muy frustrante. El cmdlet Invoke-Command es realmente muy útil para ejecutar scripts o comandos de forma remota, pero solo funciona si WinRM (Administración remota de Windows) está configurado correctamente. Normalmente, los problemas se producen porque WinRM no está habilitado en el equipo de destino o porque los firewalls bloquean las solicitudes entrantes. Configurarlo correctamente puede parecer un juego de azar, sobre todo si no estás familiarizado con los comandos exactos o la ruta para cambiar los perfiles de red o las reglas del firewall. Esta guía explica cómo habilitar WinRM correctamente, garantizar que tu red esté configurada para la administración remota y, posteriormente, cómo ejecutar comandos en sistemas remotos sin complicaciones.
Cómo habilitar PowerShell Remoting (WinRM) en Windows
Habilitar el servicio WinRM: algo imprescindible para que los comandos remotos funcionen
¿Cuál es la razón principal por la que Invoke-Command no se conecta? WinRM no está habilitado o no está configurado con las reglas de red correctas. Primero, necesita que el servicio WinRM esté ejecutándose y configurado. Para comprobar si WinRM ya está ejecutándose y escuchando, ejecute esto en PowerShell en el equipo de destino:
Get-Service -Name "*WinRM*" | fl WinRM, State Get-Item wsman:\localhost\Listener
Si no está configurado, no te preocupes. En la máquina de destino, ejecuta:
winrm quickconfig
Este comando realiza varias funciones: inicia el servicio WinRM, lo configura para que se inicie automáticamente, crea un agente de escucha predeterminado y agrega excepciones al firewall. A veces, basta con ejecutarlo Enable-PSRemoting -Forcedentro de PowerShell como administrador, especialmente si intenta hacerlo de forma remota o mediante scripts. Tenga en cuenta que, en algunas configuraciones, podría necesitar ajustar su perfil de red a Privado o Dominio, ya que PowerShell remoto no funcionará correctamente en redes públicas de forma predeterminada.
Set-NetFirewallRule -Name "WINRM-HTTP-In-TCP" –RemoteAddress Any
Esta línea permite el tráfico entrante de WinRM independientemente de la dirección de red, lo que resulta útil si se trabaja con varios segmentos de subred o configuraciones de red complejas. Recuerde que, por supuesto, Windows a veces tiene que complicarlo más de lo necesario.
Hosts de confianza: cuando se trabaja con grupos de trabajo o direcciones IP
Si sus sistemas no están en un dominio o se conecta por IP, deberá agregar esas máquinas remotas a su lista de hosts de confianza. Esto es un poco como una medida de «seguridad por conveniencia», pero es lo que se necesita. Ejecute:
Set-Item wsman:\localhost\Client\TrustedHosts -Value "192.168.1.201"
O, si te sientes imprudente, simplemente permite todo:
Set-Item wsman:\localhost\Client\TrustedHosts -Value "*"
No olvides que después tendrás que reiniciar el servicio WinRM:
Restart-Service WinRM
Uso de Invoke-Commands para ejecutar comandos en computadoras remotas
Ejecutar un solo comando: sencillo pero requiere una configuración correcta
Una vez configurado WinRM y definidas las reglas de red, usar Invoke-Command solo requiere especificar la máquina de destino y lo que se desea ejecutar. Por ejemplo:
Invoke-Command -ComputerName dc01 -ScriptBlock { Get-Service wuauclt }
Esto le pedirá a la máquina remota dc01 que le indique si el Servicio de Actualización de Windows se está ejecutando. Verá el estado del servicio impreso: en una configuración funcionó perfectamente; en otra, podría haber algunos problemas de autenticación, así que revise sus permisos y reglas de red.
$cred = Get-Credential Invoke-Command -ComputerName dc01 -Credential $cred -ScriptBlock { Get-NetAdapter }
Esto suele ser útil si su usuario actual no forma parte de los grupos de Administración remota o Administración en el equipo de destino. Tenga en cuenta que se requieren muchos permisos y, a veces, las políticas de seguridad de PowerShell bloquean ciertos comandos remotos.
Ejecutar varios comandos o scripts de forma remota: sí, puedes hacerlo
¿Quieres hacer más de una cosa a la vez? Simplemente separa los comandos con punto y coma dentro del ScriptBlock:
Invoke-Command -ComputerName dc01 -ScriptBlock { Get-TimeZone; Set-TimeZone -Name "Central Europe Standard Time" }
Y si tienes un script guardado en algún lugar, como C:\PS\CheckStatus.ps1, puedes ejecutarlo de forma remota con:
Invoke-Command -ComputerName dc01 -FilePath "C:\PS\CheckStatus.ps1"
De esta forma, no es necesario copiar scripts manualmente a sistemas remotos y se evitan los errores de política de ejecución. Resulta práctico para trabajos por lotes o scripts de administración que se ejecutan con frecuencia.
Ejecutar comandos en varias computadoras a la vez
Comandos paralelos para un grupo de servidores
Si gestionas una flota de servidores, ejecutar comandos en serie sería un fastidio. Por suerte, Invoke-Command permite la ejecución en paralelo. Simplemente enumera tus servidores separados por comas:
Invoke-Command server1, server2, server3 -ScriptBlock { get-date }
También puedes almacenar los nombres en una matriz para reutilizarlos:
$servers = @("server1", "server2", "server3") Invoke-Command -ComputerName $servers -ScriptBlock { get-date }
Invoke-Command -ComputerName (Get-Content c:\ps\servers.txt) -ScriptBlock { Restart-Service spooler }
Si está extrayendo nombres de host de Active Directory, el cmdlet Get-ADComputer ayuda a filtrar determinados sistemas:
$computers = (Get-ADComputer -Filter 'OperatingSystem -like "*Windows server*" -and Enabled -eq "true"').Name Invoke-Command -ComputerName $computers -ScriptBlock { Get-EventLog -LogName System -Newest 10 } -ErrorAction SilentlyContinue
¿Y si uno o más destinos están desconectados u ocupados? El parámetro -ErrorAction SilentlyContinue mantiene el script funcionando sin problemas. Además, para ver qué máquina respondió, use la variable PSComputerName dentro de su ScriptBlock:
$results = Invoke-Command -ComputerName $computers -ScriptBlock { get-date } $results | Select-Object PSComputerName, *
Conexiones persistentes remotas de PowerShell: ahorre tiempo y evite problemas
Crea una sesión que perdure
Si ejecuta varios comandos en la misma máquina remota, conviene mantener una sesión activa en lugar de reconectarse cada vez. A continuación, se explica cómo crear y usar una sesión persistente:
$session = New-PSSession -ComputerName Server01, Server02 Invoke-Command -Session $session -ScriptBlock { Get-ComputerInfo | select OsLastBootUpTime }
Una vez que hayas terminado, cierra esa sesión con:
Remove-PSSession $session
Esta configuración puede ahorrar mucho tiempo al administrar varios servidores, especialmente si ejecuta varios comandos en un script o una tarea programada. Tenga en cuenta que las sesiones pueden permanecer en la memoria, así que ciérrelas cuando ya no las necesite. Además, algunas configuraciones podrían requerir ajustes adicionales de seguridad o cambios de política para permitir sesiones persistentes.
Sinceramente, configurar la administración remota de PowerShell puede parecer un reto al principio, pero una vez que lo dominas, es bastante potente. Solo recuerda revisar las reglas de red y firewall, y ten paciencia con las peculiaridades.