Cómo Crear y Administrar Unidades de Temporizador Systemd

Cree, habilite, supervise y solucione problemas de unidades de temporizador de systemd con ejemplos prácticos de `.timer`, `.service`, `systemctl` y `journalctl`.

Cómo Crear y Gestionar Unidades de Temporizador de Systemd

Las unidades de temporizador de Systemd programan trabajos en Linux sin depender de cron. Si necesita que su servidor ejecute una copia de seguridad, una tarea de limpieza, una verificación de estado o un informe en un momento predecible, un temporizador de systemd le ofrece programación, aislamiento de servicios, manejo de dependencias y registros en un solo lugar.

La idea clave es simple: el archivo .timer dice cuándo ejecutar, y el archivo .service dice qué ejecutar. Esta división facilita la inspección de los temporizadores con systemctl y la depuración con journalctl.

Comprendiendo la Estructura de una Unidad de Temporizador de Systemd

Una unidad de temporizador de systemd siempre está emparejada con una unidad de servicio correspondiente (u otro tipo de unidad) que está destinada a activar. La unidad de temporizador define cuándo se debe activar la unidad asociada, mientras que la unidad de servicio define qué acción realizar. Ambas unidades generalmente residen en el mismo directorio, a menudo /etc/systemd/system/ para unidades personalizadas.

Un archivo de unidad de temporizador típico tiene la extensión .timer, y su archivo de unidad de servicio asociado tiene la extensión .service. Por ejemplo, si desea programar una tarea definida en mytask.service, crearía un archivo mytask.timer.

Ejemplo: mytask.timer

[Unit]
Description=Ejecutar mi tarea personalizada diariamente

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target

Analicemos las secciones clave:

  • Sección [Unit]:

    • Description: Una descripción legible por humanos del temporizador. Esto es útil para la identificación en las salidas de estado.
  • Sección [Timer]: Este es el núcleo de la unidad de temporizador, definiendo la programación.

    • OnCalendar=daily: Esta directiva especifica cuándo debe activarse el temporizador. daily es una abreviatura para la medianoche de cada día. Otros ejemplos incluyen:
      • hourly: Cada hora.
      • weekly: Cada semana (equivalente a Mon *-*-* 00:00:00).
      • Sun *-*-* 10:00: Todos los domingos a las 10 AM.
      • *-*-15 14:30: El día 15 de cada mes a las 2:30 PM.
      • Mon..Fri *-*-* 09:00: Días laborables a las 9 AM.
    • Persistent=true: Si se establece en true, el temporizador se activará tan pronto como sea posible si el evento ocurrió mientras el sistema estaba apagado. Para los temporizadores OnCalendar, esto significa que si el sistema estaba apagado durante la hora programada, el temporizador se activará una vez que el sistema se inicie y el temporizador se active.
    • OnBootSec=: Activa el temporizador un tiempo específico después de que el sistema arranque. Por ejemplo, OnBootSec=15min se activaría 15 minutos después del arranque.
    • OnUnitActiveSec=: Activa el temporizador un tiempo específico después de que la unidad que activa se haya activado por última vez. Por ejemplo, OnUnitActiveSec=1h programa otra ejecución una hora después de que el servicio asociado se haya activado por última vez.
    • OnUnitInactiveSec=: Activa el temporizador un tiempo específico después de que la unidad que activa se haya desactivado por última vez.
    • AccuracySec=: Especifica la precisión del temporizador. Systemd intenta activar el sistema para los temporizadores solo si el evento está dentro de esta ventana de tiempo, lo que ayuda a ahorrar energía. El valor predeterminado es 1min.
    • RandomizedDelaySec=: Agrega un retraso aleatorio a la activación del temporizador, hasta la duración especificada. Útil para distribuir la carga.
  • Sección [Install]: Esta sección define cómo se puede habilitar la unidad de temporizador.

    • WantedBy=timers.target: Esta directiva asegura que cuando el temporizador está habilitado, se convierta en parte de timers.target, que es un objetivo estándar que incluye todos los temporizadores activos. Esto significa que el temporizador se iniciará automáticamente al arrancar una vez habilitado.

Ejemplo: mytask.service

[Unit]
Description=Servicio de mi tarea personalizada

[Service]
Type=oneshot
ExecStart=/usr/local/bin/my_custom_script.sh
User=myuser
Group=mygroup

[Install]
WantedBy=multi-user.target
  • Sección [Unit]:

    • Description: Una descripción del servicio.
  • Sección [Service]: Esto define el servicio en sí.

    • Type=oneshot: Adecuado para tareas que se ejecutan una vez y luego salen. Existen otros tipos para demonios de larga duración.
    • ExecStart: El comando a ejecutar. Asegúrese de que el script tenga permisos de ejecución.
    • User/Group: Especifica el usuario y el grupo bajo los cuales se debe ejecutar el comando. Es una buena práctica no ejecutar tareas como root a menos que sea absolutamente necesario.
  • Sección [Install]: Esta sección generalmente no es necesaria para un servicio oneshot que solo debe ser iniciado por un temporizador. Habilite el temporizador, no el servicio.

Creando y Habilitando Unidades de Temporizador

Siga estos pasos para crear y gestionar sus unidades de temporizador de systemd:

  1. Crear el Archivo de Unidad de Servicio: Defina su tarea en un archivo .service. Colóquelo en /etc/systemd/system/ (o ~/.config/systemd/user/ para temporizadores específicos de usuario).

    sudo nano /etc/systemd/system/mytask.service
    

    Pegue el contenido de ejemplo del servicio anterior y guarde.

  2. Crear el Archivo de Unidad de Temporizador: Defina la programación en un archivo .timer correspondiente. Colóquelo en el mismo directorio que el archivo de servicio.

    sudo nano /etc/systemd/system/mytask.timer
    

    Pegue el contenido de ejemplo del temporizador anterior y guarde.

  3. Recargar el Demonio de Systemd: Después de crear o modificar archivos de unidad, debe indicarle a systemd que recargue su configuración.

    sudo systemctl daemon-reload
    
  4. Habilitar el Temporizador: Para que el temporizador se inicie automáticamente al arrancar, habilítelo.

    sudo systemctl enable mytask.timer
    

    Nota: NO habilite el archivo de servicio si está destinado únicamente a ser activado por el temporizador.

  5. Iniciar el Temporizador: Inicie el temporizador inmediatamente. Luego se ejecutará según su programación.

    sudo systemctl start mytask.timer
    

Gestionando y Monitoreando Unidades de Temporizador

Systemd proporciona varios comandos systemctl para gestionar y monitorear sus temporizadores:

  • Listar todos los temporizadores: Vea todos los temporizadores activos e inactivos.

    systemctl list-timers
    

    Este comando proporciona una salida como:

    NEXT                        LEFT        LAST        PASSED      UNIT          ACTIVATES
    Tue 2023-10-27 08:00:00 UTC 10h left    Wed 2023-10-26 08:00:00 UTC 14h ago       mytask.timer  mytask.service
    

    Esto muestra cuándo está programado que se ejecute el temporizador, cuánto tiempo falta, cuándo se ejecutó por última vez y qué servicio activa.

  • Listar temporizadores para una unidad específica: Si desea ver los temporizadores relacionados con un servicio específico.

    systemctl list-timers --all | grep mytask.service
    
  • Verificar el Estado del Temporizador: Obtenga información detallada sobre un temporizador específico.

    systemctl status mytask.timer
    

    Esto mostrará si el temporizador está activo, cuándo está programado para ejecutarse a continuación y las entradas de registro recientes.

  • Ver Registros del Servicio: Para ver la salida y el estado de la tarea ejecutada por el temporizador, verifique los registros del servicio asociado.

    journalctl -u mytask.service
    

    También puede seguir los registros en tiempo real:

    journalctl -f -u mytask.service
    
  • Detener un Temporizador: Si necesita deshabilitar temporalmente un temporizador.

    sudo systemctl stop mytask.timer
    
  • Deshabilitar un Temporizador: Para evitar que un temporizador se inicie al arrancar y detenerlo si se está ejecutando.

    sudo systemctl disable --now mytask.timer
    

Configuraciones Avanzadas de Temporizador

Estableciendo Intervalos Específicos

En lugar de daily o hourly, puede definir intervalos más precisos:

  • Cada N minutos: OnUnitActiveSec=15min (se ejecuta 15 minutos después de que el servicio se haya activado por última vez).
  • Horas específicas: OnCalendar=*-*-* 02:30:00 (se ejecuta diariamente a las 2:30 AM).
  • Combinando condiciones: OnCalendar=Mon..Fri *-*-* 08:00:00 (se ejecuta los días laborables a las 8 AM).

Usando AccuracySec para Ahorrar Energía

Si su tarea no necesita ejecutarse en un momento exacto, considere usar AccuracySec. Por ejemplo, AccuracySec=5min le dice a systemd que está bien activar el sistema dentro de los 5 minutos de la hora programada. Esto permite que systemd agrupe eventos de temporizador y potencialmente mantenga el sistema en un estado de menor consumo de energía por más tiempo.

[Timer]
OnCalendar=hourly
AccuracySec=5min

Persistent vs. WakeSystem

  • Persistent=true asegura que si se pierde un evento OnCalendar debido a que el sistema está apagado, se ejecutará una vez en el próximo arranque. Esto es crucial para tareas que no deben omitirse.
  • WakeSystem=true le pide a systemd que active el sistema desde la suspensión para el temporizador si el sistema y el hardware lo soportan. No es lo mismo que decidir si la máquina está con alimentación de CA o batería.

Temporizadores vs. Cron

Característica Temporizadores de Systemd Cron
Integración Integración profunda con servicios y objetivos de systemd Utilidad independiente
Programación Flexible (calendario, relativo, basado en arranque) Expresiones basadas principalmente en tiempo
Registro Centralizado a través de journalctl Disperso (/var/log/syslog, /var/log/cron.log)
Manejo de Errores Puede vincular acciones a fallos de servicio Notificaciones básicas por correo
Dependencias Puede depender de que otros servicios estén activos Limitado
Ejecución Puede ejecutarse como usuarios y grupos específicos Puede ejecutarse como usuarios específicos a través de crontab
Gestión de Energía Se puede optimizar para ahorrar energía (AccuracySec) Control menos directo

Cuándo elegir Temporizadores de Systemd:

  • Cuando necesita una integración más estrecha con otros servicios de systemd.
  • Cuando el registro centralizado y una depuración más fácil son prioridades.
  • Cuando requiere opciones de programación más avanzadas (por ejemplo, tiempo desde la última ejecución).
  • Para tareas relacionadas con el estado del sistema o la gestión de energía.

Cuándo Cron podría ser aún preferido:

  • Para tareas independientes muy simples en sistemas que no adoptan completamente systemd.
  • Para máxima compatibilidad entre diferentes distribuciones de Linux y sistemas más antiguos.

Solución de Problemas Comunes

  • La tarea no se ejecuta:
    • Verifique el estado del temporizador: systemctl status mytask.timer. Busque mensajes Active: active y Triggered....
    • Verifique los registros del servicio: journalctl -u mytask.service. Asegúrese de que el script sea ejecutable y no tenga errores.
    • Verifique la sintaxis de OnCalendar: Use systemd-analyze calendar 'su-cadena-de-calendario' para probar.
    • Asegúrese de que el temporizador esté habilitado e iniciado: systemctl list-timers --all.
  • La tarea se ejecuta demasiado temprano/tarde:
    • Verifique AccuracySec y RandomizedDelaySec.
    • Asegúrese de que el reloj del sistema sea preciso (timedatectl status).
  • Errores de permiso:
    • Confirme que el User y Group especificados en el archivo .service tengan los permisos necesarios para el script y cualquier archivo al que acceda.
    • Si no se especifica ningún usuario, el valor predeterminado es root. Tenga cuidado con los privilegios de root.

Conclusión

Use un temporizador de systemd cuando el trabajo pertenezca a la capa de servicio de la máquina: copias de seguridad, tareas de limpieza, comprobaciones de monitoreo, enlaces de renovación de certificados y otros trabajos operativos. Cree el servicio primero, cree el temporizador a continuación, ejecute systemctl daemon-reload, habilite e inicie el temporizador, luego verifíquelo con systemctl list-timers --all y journalctl -u su.servicio.