Systemd timers: la alternativa moderna a cron que necesitabas

Etiquetas:

Por qué dejé cron

Llevo años usando cron en mis servidores. Es simple, confiable y funciona. Pero hace poco descubrí systemd timers y no vuelvo atrás. La razón principal: logs integrados en journald, sin archivos .log dando vueltas por el sistema, y mejor control sobre qué pasa cuando el servidor arranca o reinicia.

En mi caso específico, tenía un backup que no se ejecutaba si el servidor estaba apagado a la hora programada. Con cron, simplemente se perdía. Con systemd timers y Persistent=true, la tarea se ejecuta en cuanto el servidor se enciende.

Estructura básica: .service + .timer

Systemd necesita dos archivos:

El servicio (/etc/systemd/system/mibackup.service):

[Unit]
Description=Backup diario de datos
After=network.target

[Service]
Type=oneshot
User=backup
ExecStart=/usr/local/bin/backup.sh
StandardOutput=journal
StandardError=journal

El timer (/etc/systemd/system/mibackup.timer):

[Unit]
Description=Ejecuta backup diariamente

[Timer]
OnCalendar=daily
OnCalendar=*-*-* 03:00:00
Persistent=true
Accuracy=1min

[Install]
WantedBy=timers.target

Luego:

sudo systemctl daemon-reload
sudo systemctl enable --now mibackup.timer

OnCalendar: la sintaxis que necesitas

OnCalendar es el cron de systemd, pero más legible:

  • daily → todos los días a medianoche
  • weekly → cada lunes a medianoche
  • hourly → cada hora
  • *-*-* 03:00:00 → todos los días a las 3 AM
  • Mon *-*-* 14:30:00 → cada lunes a las 14:30
  • *-01,04,07,10-01 00:00:00 → primero de cada trimestre

Puedes combinar múltiples líneas OnCalendar:

OnCalendar=*-*-* 03:00:00
OnCalendar=*-*-* 15:00:00

Esto ejecuta la tarea dos veces al día.

Persistent=true: el cambio que me convenció

Por defecto, si tu servidor está apagado cuando se programa una tarea, systemd simplemente la ignora. Con Persistent=true, systemd remembers y ejecuta la tarea la próxima vez que arranque.

En mi servidor doméstico, esto es crítico. No siempre está encendido, y necesito garantizar que mis backups se ejecuten aunque hayan pasado horas.

[Timer]
OnCalendar=daily
Persistent=true

Type=oneshot: para tareas que terminan

El parámetro Type=oneshot en el .service indica que el proceso terminará. Es lo normal para scripts de backup, sincronización, etc.

Si usas Type=simple (el default), systemd espera que el proceso se mantenga ejecutándose. No es lo que queremos aquí.

Ver logs sin archivos externos

Aquí está lo mejor: olvídate de >> /var/log/mibackup.log.

Los logs van directo a journald:

# Ver los últimos logs del timer
journalctl -u mibackup.service -n 50

# Ver en tiempo real
journalctl -u mibackup.service -f

# Los últimos 2 horas
journalctl -u mibackup.service --since "2 hours ago"

# Con niveles de prioridad
journalctl -u mibackup.service -p err

Dentro de tu script puedes loguear con echo o logger:

#!/bin/bash
logger "Iniciando backup..."
/backup/script.sh
logger "Backup completado"

Todo se captura automáticamente.

Checklist de lo que hicimos

  1. ✅ Creaste un .service con Type=oneshot
  2. ✅ Creaste un .timer con OnCalendar y Persistent=true
  3. ✅ Recargaste systemd y activaste el timer
  4. ✅ Verificas logs con journalctl, sin archivos de log extra

Consejo final

Antes de depender de un timer, pruébalo manualmente:

# Ejecutar el servicio ahora
sudo systemctl start mibackup.service

# Ver qué pasó
journalctl -u mibackup.service -n 20

Eso. Systemd timers no es la panacea, pero para tareas programadas en servidores modernos, es superior a cron en casi todos los aspectos. Los logs centralizados en journald, combinados con Persistent=true, hacen que sea imposible no recomendarlo.

En mi servidor doméstico, todos los backups, limpiezas de caché y sincronizaciones de datos usan timers. Cero archivos de log sueltos. Todo integrado.


Equipamiento recomendado

Enlaces de afiliado. Sin coste extra para ti.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *