Linux··8 min de lectura

De cron a systemd timers: cuándo migrar y cómo hacerlo bien

Cron sigue siendo válido, pero los timers de systemd resuelven sus limitaciones más molestas: logs, dependencias, ejecución perdida y policies de reinicio.

Cron: bueno para lo simple

Cron nació en 1975 y sigue siendo válido para tareas simples: backup diario, rotación de logs, ping de healthcheck. La sintaxis minuto hora día mes diasem comando la conoce todo administrador y funciona en cualquier Unix. Nuestro generador de expresiones cron ayuda a construir la línea correcta.

Sin embargo, cron acumula limitaciones que en 2026 empiezan a pesar.

Los límites reales de cron

1. Logging escaso — si no rediriges stdout/stderr, no sabes qué pasó cuando algo falla. 2. Sin dependencias — no puedes decir "ejecuta este job después de aquel". 3. Ejecuciones perdidas — si el servidor estaba apagado a la hora del disparo, la tarea no se ejecuta cuando vuelve. 4. Sin política de reinicio — si falla, no reintenta. 5. Sin límites de recursos — el job puede comerse toda la RAM. 6. Sin aislamiento — corre con acceso completo al filesystem.

Un timer systemd mínimo

Un timer necesita dos units: uno .service con la tarea, otro .timer con la programación.


# /etc/systemd/system/backup.service
[Unit]
Description=Backup diario

[Service]
Type=oneshot
User=backup
ExecStart=/opt/scripts/backup.sh
Nice=15
IOSchedulingClass=best-effort
IOSchedulingPriority=7

# /etc/systemd/system/backup.timer
[Unit]
Description=Ejecutar backup diario

[Timer]
OnCalendar=*-*-* 03:00:00
RandomizedDelaySec=15min
Persistent=true

[Install]
WantedBy=timers.target

Activa:


sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
systemctl list-timers   # ver próximos disparos
journalctl -u backup.service -f

Sintaxis OnCalendar: mucho más legible

  • daily — cada día a las 00:00
  • hourly — al minuto 0 de cada hora
  • --* 03:00:00 — cada día a las 3
  • Mon..Fri --* 09:00 — lunes a viernes a las 9
  • *:0/15 — cada 15 minutos
  • Mon --* 06:00 — cada lunes a las 6

Analiza cualquier expresión con systemd-analyze calendar '<expresión>'.

Persistent: no perder ejecuciones

Persistent=true guarda el último disparo en disco. Si el servidor estaba apagado a la hora de la ejecución, en cuanto arranca ejecuta la tarea pendiente. Cron nunca supo hacer esto sin ayudas como anacron.

RandomizedDelaySec: jitter contra colisiones

Si 100 servidores ejecutan la misma tarea a las 3:00, saturan la red y el destino de backups. RandomizedDelaySec=15min reparte los disparos en una ventana de 15 minutos.

Aislamiento y hardening por defecto

Un service de systemd puede aplicar todas las directivas de sandboxing: ProtectSystem=strict, NoNewPrivileges=yes, MemoryMax=1G, PrivateNetwork=yes si no necesita red. Un cron job hereda tu entorno con acceso total.

Cuándo NO migrar

  • Scripts triviales de usuario en ~/ — sigue con crontab -e.
  • Sistemas sin systemd (Alpine, algunos BSDs, muchos containers minimalistas).
  • Cuando otra persona hará mantenimiento y solo conoce cron.

Guía rápida de migración

1. Identifica cada línea de tu crontab. 2. Genera el par service/timer correspondiente (o usa nuestro generador systemd). 3. Prueba con systemctl start miservicio.service que la ejecución manual funcione. 4. Activa el timer con systemctl enable --now. 5. Comprueba en systemctl list-timers la próxima ejecución. 6. Elimina la línea del crontab.

Alternativas más allá de cron y systemd

  • Kubernetes CronJob — si tu tarea vive en un cluster, define un CronJob y olvídate de programar en cada nodo.
  • Rundeck, Airflow, Temporal — para dependencias complejas entre tareas, retries inteligentes, UI y auditoría.
  • Cronitor, Healthchecks.io — servicios de monitorización externa que te avisan si un job no se ejecutó.

Para el 90% de tareas de un sysadmin en un servidor tradicional, los timers de systemd son el sweet spot: la simplicidad de cron con las capacidades de un scheduler moderno.

Herramientas relacionadas

Sigue leyendo