Cómo programar reinicio automático en Windows Server VPS
Aprende a programar reinicio automático en Windows Server con el Programador de tareas y PowerShell, con ventanas de mantenimiento seguras y registros.
Los servidores Windows que ejecutan aplicaciones de larga duración — IIS hospedando APIs, servicios .NET, instancias de SQL Server, pasarelas de integración — se degradan gradualmente sin reinicio. La memoria se fragmenta, los handles del kernel se acumulan, y las actualizaciones pendientes quedan en un estado intermedio que solo un reinicio resuelve. En producción, la práctica estable es programar el reinicio periódico en una ventana de bajo tráfico.
Este tutorial cubre cómo configurar el reinicio automático en un Windows Server VPS mediante el Programador de tareas (interfaz gráfica y línea de comandos) y mediante PowerShell. También muestra cómo añadir avisos para las sesiones RDP activas, condiciones de aborto basadas en carga, y logs auditables para confirmar que cada ventana se ejecutó. Tiempo estimado: 25 minutos.
La audiencia es el sysadmin Windows que ya tiene el servidor configurado y quiere automatizar el ciclo de mantenimiento sin depender de una conexión manual el domingo de madrugada.
Requisitos previos
Windows Server 2019, 2022 o 2025 con acceso administrativo (RDP o consola). PowerShell 5.1 o superior (ya viene instalado). La cuenta usada para crear la tarea necesita tener el derecho de inicio de sesión como servicio y el privilegio de apagar el sistema — los administradores locales tienen ambos por defecto.
Antes de empezar, confirma los datos básicos de la sesión. Estos valores se referencian en los comandos de abajo:
Windows Server 2022 Administrator PowerShell 5.1+ Domingo 04:00 Decisión: Programador de tareas o PowerShell
Existen dos caminos para programar el reinicio en Windows. Cada uno cubre un escenario:
| Método | Cuándo usar | Limitación |
|---|---|---|
| Programador vía GUI | Configuración única, el sysadmin prefiere clic | Difícil de versionar y replicar |
| Programador vía schtasks | Script único reproducible | Sintaxis verbosa para condiciones complejas |
| PowerShell Register-ScheduledTask | Versionado, lógica condicional, múltiples servidores | Curva de aprendizaje mayor |
Para un servidor único, el Programador vía GUI es suficiente. Para una flota de 5+ servidores o si usas configuración como código, PowerShell es el camino. Vamos a cubrir los tres métodos — elige el que encaje.
Método 1: Programador de tareas vía interfaz gráfica
La interfaz gráfica es la forma más rápida para un servidor aislado. Los pasos siguientes crean una tarea que reinicia el servidor todos los domingos a las 4 de la madrugada.
Abre el Programador de tareas. Pulsa Win + R, escribe taskschd.msc y pulsa Enter.
En el panel derecho, haz clic en “Crear tarea” (no “Tarea básica” — necesitas las opciones avanzadas).
En la pestaña “General”, rellena:
- Nombre:
Reboot Semanal Mantenimiento - Descripción:
Reinicio automatico de mantenimiento - domingo 04:00 - Selecciona “Ejecutar con los privilegios más altos”
- En “Configurar para”, selecciona la versión de tu Windows Server
Marca “Ejecutar tanto si el usuario inició sesión como si no” — esto garantiza la ejecución incluso sin sesión RDP activa.
Pestaña “Desencadenadores” → “Nuevo”. Configura:
- Iniciar la tarea: “Según una programación”
- Semanalmente, repetir cada 1 semana
- Día: Domingo
- Hora: 04:00:00
En las opciones avanzadas, marca “Habilitado” y déjalo sin caducidad.
Pestaña “Acciones” → “Nueva”. Configura:
- Acción: “Iniciar un programa”
- Programa o script:
shutdown.exe - Agregar argumentos:
/r /t 600 /c "Mantenimiento semanal automatico" /f
El parámetro /r fuerza el reinicio (no apagado), /t 600 da 10 minutos de aviso a los usuarios conectados, /c define el mensaje visible, y /f fuerza el cierre de aplicaciones que no responden.
Pestaña “Condiciones”. Desmarca “Iniciar la tarea solo si el equipo está inactivo” e “Iniciar la tarea solo si el equipo está conectado a la corriente alterna”. En un servidor, esas condiciones no tienen sentido y pueden impedir la ejecución.
Pestaña “Configuración”. Marca “Permitir que la tarea se ejecute a petición” y “Si la tarea falla, reiniciarla cada 1 minuto, intentar reiniciar hasta 3 veces”.
Haz clic en OK. Se te pedirá introducir la contraseña de la cuenta — proporciónala.
Haz clic con el botón derecho sobre la tarea creada y selecciona “Ejecutar”. El reinicio debe dispararse con aviso visible. Reconéctate después y confirma que todo arrancó. Una tarea que nunca se probó manualmente suele fallar en la primera ejecución programada.
Método 2: Creación vía schtasks
Para scriptar la misma programación en una línea — útil en provisioning o para documentar la configuración — usa schtasks.
Abre PowerShell como administrador (clic derecho → “Ejecutar como administrador”) y ejecuta:
schtasks /create `
/tn "Reboot Semanal Mantenimiento" `
/tr "shutdown.exe /r /t 600 /c 'Mantenimiento semanal automatico' /f" `
/sc weekly /d SUN /st 04:00 `
/ru "SYSTEM" /rl HIGHEST /fEl parámetro /ru SYSTEM evita la dependencia de la contraseña de una cuenta — la tarea se ejecuta como sistema. /rl HIGHEST garantiza privilegios elevados, y /f sobrescribe si la tarea ya existe.
Verifica que la tarea se creó:
schtasks /query /tn "Reboot Semanal Mantenimiento" /v /fo LISTLa salida muestra el próximo horario de ejecución, el estado, y la última ejecución. Confirma que “Próxima ejecución” cae el próximo domingo a las 04:00.
Método 3: PowerShell con lógica condicional
Cuando necesitas condiciones más complejas — abortar el reinicio si la CPU está por encima del 80%, o si un servicio crítico está en una transacción — encapsula la lógica en un script y prográmalo con Register-ScheduledTask.
Crea el script envoltorio en C:\Scripts\reboot-semanal.ps1:
$LogPath = "C:\Scripts\reboot-semanal.log"
$Stamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
# Comprueba carga media de CPU de los ultimos 60s
$cpu = (Get-Counter '\Processor(_Total)\% Processor Time' `
-SampleInterval 5 -MaxSamples 12).CounterSamples |
Measure-Object -Property CookedValue -Average
if ($cpu.Average -gt 80) {
Add-Content $LogPath "$Stamp ABORT cpu=$([math]::Round($cpu.Average,1))%"
exit 1
}
# Comprueba servicio critico (ajusta el nombre)
$svc = Get-Service -Name "MiServicioCritico" -ErrorAction SilentlyContinue
if ($svc -and $svc.Status -eq 'Running') {
# Logica de health check de la aplicacion aqui
Add-Content $LogPath "$Stamp OK servicio activo, continuando"
}
Add-Content $LogPath "$Stamp REBOOT iniciando shutdown /r /t 600"
Start-Process -FilePath "shutdown.exe" `
-ArgumentList "/r","/t","600","/c","Mantenimiento semanal","/f"Este script registra en un log local cada ejecución, comprueba la CPU media de 1 minuto, y solo dispara el reinicio si la condición es segura. Ajusta el nombre del servicio y los umbrales a tu escenario.
Registra la tarea con PowerShell:
$Action = New-ScheduledTaskAction `
-Execute "PowerShell.exe" `
-Argument "-ExecutionPolicy Bypass -File C:\Scripts\reboot-semanal.ps1"
$Trigger = New-ScheduledTaskTrigger `
-Weekly -DaysOfWeek Sunday -At 04:00
$Principal = New-ScheduledTaskPrincipal `
-UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest
$Settings = New-ScheduledTaskSettingsSet `
-StartWhenAvailable -DontStopOnIdleEnd `
-RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1)
Register-ScheduledTask `
-TaskName "Reboot Semanal Mantenimiento" `
-Action $Action -Trigger $Trigger `
-Principal $Principal -Settings $Settings -ForceLa flag -StartWhenAvailable es importante: si el servidor estaba apagado a la hora programada y se enciende después, la tarea se ejecuta en la siguiente oportunidad en lugar de saltarse el ciclo.
Haz commit de reboot-semanal.ps1 en un repositorio de configuración de tu infraestructura. Cuando necesites ajustar el umbral de CPU o añadir una nueva condición, lo editas una vez y lo replicas vía Group Policy o Ansible. La configuración dispersa en GUI se convierte en deuda técnica en una flota de 5+ servidores.
Verificación
Confirma que la tarea está activa y que la próxima hora es correcta:
Get-ScheduledTask -TaskName "Reboot Semanal Mantenimiento" |
Select-Object TaskName, State, @{N='Proximo';E={
(Get-ScheduledTaskInfo $_).NextRunTime
}}
Salida esperada:
TaskName State Proximo
-------- ----- -------
Reboot Semanal Mantenimiento Ready 01/06/2026 04:00:00
Para confirmar que la tarea se ejecutó tras el primer domingo, consulta el historial:
Get-ScheduledTaskInfo -TaskName "Reboot Semanal Mantenimiento"
El campo LastRunTime muestra cuándo se ejecutó y LastTaskResult debe ser 0 (éxito). Cualquier valor distinto indica un fallo — investiga vía Programador → Historial o vía Get-WinEvent en el log “Microsoft-Windows-TaskScheduler/Operational”.
Resolución de problemas
La tarea no se ejecuta, sin mensaje de error
Verifica que el historial del Programador esté habilitado. Por defecto, en algunos Windows Server viene deshabilitado, lo que impide ver lo que ocurrió. En el panel derecho del Programador, haz clic en “Habilitar Historial de Todas las Tareas”.
Después de eso, abre la tarea y mira la pestaña Historial. Si el evento es “La tarea no se inició porque la cuenta no estaba conectada” — olvidaste marcar “Ejecutar tanto si el usuario inició sesión como si no” durante la creación.
El reinicio se dispara pero el servidor no arranca
Verifica si algún servicio con inicio automático está fallando en el arranque. Ejecuta tras reconectarte:
Get-EventLog -LogName System -EntryType Error -Newest 20 |
Where-Object {$_.Source -like "*Service*"}
Un servicio atascado en estado “Starting” indefinidamente es la causa más común. Suele ser una dependencia de red o base de datos que aún no se ha estabilizado — añade un retraso en el arranque del servicio problemático.
Si el servidor entra en un bucle de reinicio, conéctate vía consola (no RDP) y deshabilita la tarea antes que nada: Disable-ScheduledTask -TaskName "Reboot Semanal Mantenimiento". En un VPS, la consola es el acceso vía panel de control — RDP no funcionará si la máquina reinicia antes de que la red arranque.
El aviso de reinicio no aparece a los usuarios RDP
El parámetro /c "mensaje" solo funciona si el usuario tiene una sesión activa en el momento en que se ejecuta shutdown /t 600. Si se conecta después del disparo, no se muestra nada. Para una notificación proactiva, añade antes del shutdown:
msg * /TIME:60 "Reinicio programado en 10 minutos - guarda tu trabajo"
msg.exe envía un broadcast a todas las sesiones activas — combinado con el aviso visual de shutdown, cubre ambos casos.
Próximos pasos
Con el ciclo de reinicio automatizado, vale la pena evolucionar en direcciones complementarias:
- Configura un health check post-reinicio mediante PowerShell que valide los servicios críticos y envíe una alerta si algo no arrancó en 5 minutos.
- Añade registro en event log (
Write-EventLog) en el script envoltorio para centralizar vía syslog o SIEM. - Documenta la ventana de mantenimiento en una status page interna para que el equipo de aplicación sepa cuándo esperar indisponibilidad.
- Combínalo con un snapshot automático previo al reinicio mediante la API de tu proveedor para un rollback rápido si algo falla.
- Considera programar Windows Update por separado para que se ejecute antes del reinicio, garantizando que el ciclo cubra las actualizaciones pendientes.
Si estás llevando esto a producción, un VPS Hostini Windows Server ya viene con consola fuera de banda en el panel — útil para recuperar el acceso si un reinicio programado rompe la red y RDP queda no disponible, evitando depender del soporte para resetear la máquina.
Preguntas frecuentes
¿Puedo programar un reinicio sin desconectar a los usuarios RDP de inmediato?
Sí. El parámetro /t de shutdown define un retraso en segundos antes del reinicio real, durante el cual los usuarios conectados reciben un aviso visual. Usa /t 600 para dar 10 minutos de margen. Combínalo con /c "mensaje" para explicar el motivo en la notificación.
¿Cómo evito que el reinicio programado se dispare si el servidor está bajo alta carga?
Añade una condición de disparo que comprueba el uso medio de CPU de los últimos minutos mediante PowerShell antes del Restart-Computer. Si supera un umbral, escribe en el event log y aborta. El Programador permite ejecutar un script envoltorio en lugar del shutdown directo.
Windows Update programa reinicios por su cuenta — ¿necesito desactivarlo?
En Windows Server, las actualizaciones automáticas normalmente respetan las horas activas y no reinician solas si usas WSUS o programación manual. Aun así, configura la política "No auto-restart with logged on users" para garantizar que solo tu tarea controla cuándo ocurre el reinicio.
¿Cómo verifico si la tarea se ejecutó realmente la semana pasada?
Abre el Programador, selecciona la tarea y haz clic en la pestaña Historial — cada ejecución queda registrada con timestamp y código de salida. Para una auditoría persistente, activa el registro en event log dentro del script (Write-EventLog) y consulta vía Get-WinEvent.
¿Puedo omitir el reinicio programado si un servicio crítico está en una transacción activa?
Sí, pero necesitas un script envoltorio. Antes del Restart-Computer, consulta el estado del servicio (Get-Service, Get-Process, o una API de health check de la aplicación) y retorna sin reiniciar si la condición no se cumple. Registra la decisión para poder rastrearla después.
¿Cuál es el impacto real de no reiniciar un Windows Server durante meses?
La memoria se fragmenta, los handles del kernel se acumulan, el pool no paginado crece y las actualizaciones pendientes quedan en estado intermedio. Las aplicaciones .NET de uptime largo muestran degradación perceptible después de 30-60 días. Reiniciar cada semana o quincena es el equilibrio habitual en producción.