Comandos PowerShell para Windows Server: Guía Práctica para Sysadmin

Comandos PowerShell esenciales para administrar Windows Server sin GUI: servicios, eventos, red, AD, procesos y automatización real en producción.

Administrar Windows Server desde la interfaz gráfica funciona, pero escala mal. No vas a reproducir 30 clics entre Server Manager, Services.msc y Event Viewer durante una ventana de mantenimiento nocturna. PowerShell cambia esa ecuación: cualquier acción de GUI tiene un cmdlet equivalente, scriptable, auditable y reproducible en cientos de servidores.

Esta guía cubre los comandos PowerShell que un sysadmin de Windows usa de verdad todos los días — gestión de servicios y procesos, lectura de eventos, configuración de red, manipulación de usuarios y Active Directory, y el camino completo para automatizar todo eso mediante Scheduled Tasks. Los ejemplos fueron probados en Windows Server 2022 con Windows PowerShell 5.1 (el default del sistema) y funcionan sin ajustes en Windows Server 2019 y 2025.

Tiempo de ejecución para recorrer todas las secciones con práctica real: alrededor de 40 minutos. Al final tendrás una sesión PowerShell elevada, varios comandos útiles en el historial y un script programado ejecutándose como demostración.

Prerrequisitos

Lo que necesitas

Windows Server 2019/2022/2025 con acceso por RDP o consola y una cuenta con privilegios administrativos. Windows PowerShell 5.1 ya viene instalado. Si vas a administrar Active Directory, el módulo RSAT-AD-PowerShell debe estar presente — instálalo con Install-WindowsFeature RSAT-AD-PowerShell en un Domain Controller o servidor miembro del dominio.

Sistema probado Windows Server 2022
PowerShell 5.1 (default)
Ejecución Sesión elevada

Antes de cualquier cosa, abre PowerShell como administrador (Win+X, después “Windows PowerShell (Admin)” o “Terminal (Admin)” en Server 2022+). Confirma la versión y la Execution Policy actual:

$PSVersionTable.PSVersion
Get-ExecutionPolicy -List

Si la Execution Policy está en Restricted en todos los ámbitos, ajústala antes de ejecutar cualquier script:

Set-ExecutionPolicy -Scope LocalMachine -ExecutionPolicy RemoteSigned -Force

Gestión de servicios de Windows

Los servicios son el pan de cada día en la administración Windows. Estos comandos reemplazan por completo el snap-in services.msc.

01

Listar servicios y filtrar por estado:

Get-Service | Where-Object { $_.Status -eq 'Stopped' -and $_.StartType -eq 'Automatic' }

Este pipeline muestra los servicios configurados como automáticos pero que están detenidos — una de las primeras señales de problema en un servidor recién iniciado. La propiedad StartType solo aparece directamente en Get-Service desde PowerShell 5.1+.

02

Iniciar, detener y reiniciar un servicio:

Start-Service -Name 'W3SVC'
Stop-Service -Name 'W3SVC' -Force
Restart-Service -Name 'W3SVC'

Usa -Force en Stop-Service cuando el servicio tiene dependientes — sin él, PowerShell pide confirmación para detener la cadena completa.

03

Auditar binario y cuenta de inicio de sesión de un servicio (útil en revisión de seguridad):

Get-CimInstance Win32_Service -Filter "Name='Spooler'" |
  Select-Object Name, PathName, StartName, State, ProcessId

PathName revela si el servicio apunta a un binario sospechoso (C:\Users\* o un directorio temporal son red flags). StartName muestra la cuenta que lo ejecuta — cuentas con privilegios excesivos en servicios de terceros son vectores comunes de escalación.

Procesos y consumo de recursos

Para diagnosticar picos de CPU o memoria sin abrir el Administrador de tareas:

04

Top 10 procesos por uso de memoria:

Get-Process |
  Sort-Object -Property WorkingSet64 -Descending |
  Select-Object -First 10 Name, Id,
    @{n='RAM_MB';e={[math]::Round($_.WorkingSet64/1MB,1)}},
    @{n='CPU_s';e={[math]::Round($_.CPU,1)}}

WorkingSet64 es la memoria física residente — el número que importa cuando el servidor está bajo presión de RAM. La propiedad CPU acumula segundos de procesador desde el inicio del proceso, así que un número alto puede ser un proceso legítimo de larga duración, no necesariamente un problema.

05

Matar un proceso colgado por nombre o PID:

Stop-Process -Name 'notepad' -Force
Stop-Process -Id 4242 -Force
Cuidado al matar procesos del sistema

Nunca uses Stop-Process sobre lsass, csrss, wininit o services — el sistema se reinicia en 60 segundos con bug check. Confirma la ruta con Get-Process antes de cualquier Stop-Process sobre un proceso desconocido.

Eventos y logs de Windows

Get-WinEvent es drásticamente más rápido que Get-EventLog porque empuja los filtros a la API ETW en lugar de cargar todo en memoria.

06

Últimos 20 errores del log System en las últimas 24h:

$ayer = (Get-Date).AddDays(-1)
Get-WinEvent -FilterHashtable @{
  LogName   = 'System'
  Level     = 2
  StartTime = $ayer
} -MaxEvents 20 | Format-Table TimeCreated, Id, ProviderName, Message -Wrap

Level 2 es Error. Usa 3 para Warning y 4 para Information. El hashtable se procesa server-side, por lo que funciona bien incluso en logs con millones de eventos.

07

Buscar intentos de inicio de sesión fallidos (Event ID 4625 del log Security):

Get-WinEvent -FilterHashtable @{
  LogName = 'Security'
  Id      = 4625
  StartTime = (Get-Date).AddHours(-6)
} | Select-Object TimeCreated, @{n='User';e={$_.Properties[5].Value}},
                  @{n='IP';e={$_.Properties[19].Value}}

El Event ID 4625 es el evento canónico de inicio de sesión fallido. En un servidor expuesto a internet (RDP, SSH, OWA), esta consulta revela bruteforce en curso. Si el volumen es alto, configura bloqueo por cuenta con Account Lockout Policy o un sistema de IP banning.

Red: configuración y diagnóstico

Estos comandos reemplazan ncpa.cpl, ipconfig, ping, tracert y netstat en entornos modernos (Windows Server 2012 R2 o superior).

08

Inventario rápido de IPs y gateways:

Get-NetIPConfiguration |
  Where-Object { $_.NetAdapter.Status -eq 'Up' } |
  Format-Table InterfaceAlias, IPv4Address, IPv4DefaultGateway, DNSServer

Muestra solo las interfaces activas. Para inspeccionar una específica:

Get-NetAdapter -Name 'Ethernet0' | Format-List Name, MacAddress, LinkSpeed, Status
09

Configurar IP estática y DNS:

New-NetIPAddress -InterfaceAlias 'Ethernet0' `
  -IPAddress '10.0.0.50' -PrefixLength 24 -DefaultGateway '10.0.0.1'

Set-DnsClientServerAddress -InterfaceAlias 'Ethernet0' `
  -ServerAddresses '1.1.1.1','8.8.8.8'
Atención en sesión RDP

Cambiar la IP de la interfaz que sostiene tu sesión RDP corta la conexión. Hazlo por consola (KVM, consola serie del proveedor) o programa una reversión automática con Register-ScheduledTask para ejecutar en 5 minutos si no confirmas el cambio.

10

Listar conexiones TCP activas con PID y proceso:

Get-NetTCPConnection -State Listen |
  Select-Object LocalAddress, LocalPort,
    @{n='Process';e={(Get-Process -Id $_.OwningProcess).Name}} |
  Sort-Object LocalPort

Reemplaza netstat -ano con la ventaja de traer ya el nombre del proceso. Útil para auditar qué puertos están abiertos y quién está escuchando.

Usuarios y Active Directory

El módulo ActiveDirectory añade más de 150 cmdlets *-AD*. Los más usados en el día a día:

11

Crear un usuario, definir contraseña y habilitarlo:

$clave = Read-Host -AsSecureString 'Contraseña inicial'
New-ADUser -Name 'Juan Pérez' -SamAccountName 'jperez' `
  -UserPrincipalName '[email protected]' `
  -AccountPassword $clave -Enabled $true `
  -ChangePasswordAtLogon $true -Path 'OU=Usuarios,DC=empresa,DC=local'

Read-Host -AsSecureString evita que la contraseña se filtre en el historial de PowerShell. ChangePasswordAtLogon $true fuerza el cambio en el primer acceso, práctica recomendada para cualquier cuenta aprovisionada.

12

Encontrar cuentas inactivas por más de 90 días (candidatas a desactivación):

Search-ADAccount -AccountInactive -TimeSpan 90.00:00:00 -UsersOnly |
  Select-Object Name, SamAccountName, LastLogonDate, Enabled |
  Sort-Object LastLogonDate

Este comando es oro para la higiene de AD. Las cuentas inactivas son un vector de compromiso porque nadie se da cuenta si son reactivadas maliciosamente.

Automatización: programar scripts sin GUI

Todo el Task Scheduler tiene equivalente en cmdlets. Este patrón reemplaza hacer clics en taskschd.msc.

13

Programar un script de mantenimiento para ejecutarse todos los días a las 3h:

$action = New-ScheduledTaskAction -Execute 'powershell.exe' `
  -Argument '-NoProfile -ExecutionPolicy Bypass -File C:\scripts\mantenimiento.ps1'

$trigger = New-ScheduledTaskTrigger -Daily -At 3am

$principal = New-ScheduledTaskPrincipal -UserId 'SYSTEM' `
  -LogonType ServiceAccount -RunLevel Highest

$settings = New-ScheduledTaskSettingsSet -StartWhenAvailable `
  -DontStopOnIdleEnd -ExecutionTimeLimit (New-TimeSpan -Hours 2)

Register-ScheduledTask -TaskName 'Mantenimiento_Diario' `
  -Action $action -Trigger $trigger -Principal $principal -Settings $settings

-NoProfile evita cargar perfiles de usuario (que pueden tardar segundos). -StartWhenAvailable garantiza que la tarea se ejecute cuando el servidor vuelve de un downtime, incluso si se perdió el horario programado.

Registra siempre logs en el script

Coloca Start-Transcript -Path "C:\logs\mantenimiento_$(Get-Date -f yyyyMMdd).log" -Append al inicio del mantenimiento.ps1 y Stop-Transcript al final. Sin esto, el debug de un fallo en una tarea programada es ciego — el output del script desaparece cuando la sesión termina.

Verificación

Para confirmar que todo está en su lugar, ejecuta este health check rápido:

Write-Host "PowerShell $($PSVersionTable.PSVersion)"
Write-Host "Execution Policy: $(Get-ExecutionPolicy)"
Write-Host "Tareas activas: $((Get-ScheduledTask | Where-Object State -eq 'Ready').Count)"
Write-Host "Servicios Stopped (auto): $((Get-Service | Where-Object { $_.Status -eq 'Stopped' -and $_.StartType -eq 'Automatic' }).Count)"

Output esperado en un servidor saludable: versión 5.1 o superior, ExecutionPolicy RemoteSigned, ningún servicio automático detenido sin motivo, y al menos la tarea recién creada visible.

Siguientes pasos

  • Estudia about_Splatting (Get-Help about_Splatting) — pasar parámetros mediante hashtable hace que los scripts largos sean legibles.
  • Aprende about_Try_Catch_Finally para un manejo de errores adecuado en scripts programados, evitando fallos silenciosos.
  • Configura DSC (Desired State Configuration) o Ansible para una gestión declarativa de configuración en una flota de servidores.
  • Considera migrar a PowerShell 7 en los servidores donde necesites pipeline paralelo (ForEach-Object -Parallel) o módulos multiplataforma.

Si estás ejecutando estos comandos contra Windows Server en producción, una VPS Windows de Hostini ya viene con licencia activada, consola KVM disponible para recuperación cuando te quedas fuera por la red, y snapshots bajo demanda para probar cambios de configuración con seguridad.

Preguntas frecuentes

¿Necesito instalar algo para usar estos comandos en Windows Server?

No. Windows PowerShell 5.1 viene instalado en Windows Server 2016, 2019, 2022 y 2025. El módulo ActiveDirectory requiere Remote Server Administration Tools (RSAT), que en Windows Server se añade con `Install-WindowsFeature RSAT-AD-PowerShell`. Para PowerShell 7 multiplataforma, descarga el MSI desde el GitHub oficial — se instala en paralelo, sin reemplazar la 5.1.

¿Cómo resolver el error 'execution of scripts is disabled on this system'?

Ese error proviene de la Execution Policy. Ejecuta `Set-ExecutionPolicy -Scope LocalMachine -ExecutionPolicy RemoteSigned` en una sesión elevada. Esto permite scripts locales y exige firma digital en scripts descargados de internet. Para una ejecución puntual, usa `powershell.exe -ExecutionPolicy Bypass -File ruta.ps1`. Nunca configures como `Unrestricted` en un servidor de producción.

¿Get-Service y Get-CimInstance Win32_Service muestran lo mismo?

No exactamente. Get-Service entrega una vista simplificada (nombre, estado, start type) y es rápido. Get-CimInstance Win32_Service trae datos completos del WMI: ruta del ejecutable, cuenta de inicio de sesión, dependencias, PID cuando está en ejecución. Usa Get-Service en el día a día y Get-CimInstance cuando necesites auditar el binario o la cuenta de servicio.

¿Cómo ejecuto PowerShell en otro servidor de forma remota?

Habilita WinRM en el destino con `Enable-PSRemoting -Force`. Luego usa `Invoke-Command -ComputerName srv02 -ScriptBlock { Get-Service }` para comandos puntuales o `Enter-PSSession srv02` para una sesión interactiva. Dentro de un dominio, la autenticación Kerberos es automática. Fuera de dominio, configura TrustedHosts con `Set-Item WSMan:\localhost\Client\TrustedHosts -Value 'srv02'`.

¿Cuál es la diferencia entre Get-EventLog y Get-WinEvent?

Get-EventLog es el cmdlet heredado, solo lee los 3 logs clásicos (System, Application, Security) y es lento en registros grandes. Get-WinEvent usa la API ETW moderna, lee cualquier canal del Windows Event Log (incluyendo Microsoft-Windows-*), admite filtros XPath y XML, y es órdenes de magnitud más rápido con filtros server-side. Usa Get-WinEvent en cualquier código nuevo.

¿Puedo programar scripts PowerShell sin usar la interfaz gráfica del Task Scheduler?

Sí. Usa `New-ScheduledTaskAction` + `New-ScheduledTaskTrigger` + `Register-ScheduledTask`. Pasa siempre `-NoProfile` en el argumento de powershell.exe para no cargar perfiles lentos, registra logs con `Start-Transcript` al inicio del script, y ejecútalo como `SYSTEM` o una cuenta de servicio dedicada con `-RunLevel Highest`. Revisa el ejemplo en la sección de automatización.

Temas:
Próximos pasos Cloud Ryzen con NVMe y protección DDoS siempre activa.Pon en producción en un VPS Hostini →
¿Te resultó útil este tutorial?
Hablar por WhatsApp