8 puntos por GN⁺ 2026-06-02 | 2 comentarios | Compartir por WhatsApp
  • Los temporizadores de systemd son un reemplazo práctico de cron: ejecutan unidades como .service según una programación y hacen más clara la gestión del historial, la salida y el entorno
  • El cron tradicional tiene como puntos débiles un $PATH ambiguo, stdout/stderr que se pierde con facilidad, un historial de ejecución difícil de rastrear y una sintaxis de programación complicada de leer
  • Los temporizadores enlazan un .timer y un .service con la misma raíz de nombre, y expresan ejecuciones basadas en hora o eventos con OnCalendar, OnBootSec y OnUnitActiveSec
  • Con systemd-analyze calendar y systemctl list-timers se puede revisar la expresión de tiempo y la próxima hora de ejecución, y WakeSystem= puede reactivar la ejecución incluso desde suspensión
  • RandomizedOffsetSec y FixedRandomDelay= reducen los picos por ejecuciones simultáneas, y Persistent= compensa justo después de volver en línea las ejecuciones perdidas mientras estuvo inactivo

Por qué usar temporizadores de systemd como reemplazo de cron

  • El término cron job se usa ampliamente para referirse al componente básico de cómputo que ejecuta tareas según una programación, como “ejecuta esto todos los días” o “ejecuta aquello cada mes”, incluso cuando no se trata del demonio cron real
  • Un temporizador de systemd es una unidad de systemd que ejecuta otra unidad, normalmente una .service, siguiendo una programación específica, y puede ser un reemplazo funcional del demonio cron tradicional
  • El cron tradicional tiene varias debilidades prácticas
    • La configuración ambigua de $PATH hace difícil predecir el resultado de ejecutar scripts
    • La salida de stdout y stderr muchas veces termina en un agujero negro o se envía al sistema de correo del host
    • Es difícil rastrear y consultar el historial de ejecuciones
    • Una sintaxis de programación como 01,31 04,05 1-15 1,6 * no es fácil de leer ni intuitiva para las personas
  • Los temporizadores de systemd reducen estos problemas y al mismo tiempo ofrecen una configuración de calendario parecida a las expresiones estilo cron

Estructura básica: servicio y temporizador

  • Un temporizador de systemd necesita un objetivo de ejecución, y una unidad .service puede verse lógicamente como si fuera un script
  • Por ejemplo, si se coloca la siguiente unidad en /etc/systemd/system/roulette.service, se instala un servicio que apaga la computadora con una probabilidad de 1 entre 10
[Unit]
Description=1 in 10 chance to break your chains

[Service]
ExecStart=/usr/bin/env bash -c '[[ $(($RANDOM % 10)) == 0 ]] && systemctl poweroff || echo LIVE ANOTHER DAY'
  • ExecCondition= es una forma más integrada de expresar ejecución condicional como opción de servicio de systemd, y deja más claro a nivel de unidad si “¿debe continuar la ejecución?”
[Unit]
Description=1 in 10 chance to break your chains

[Service]
ExecCondition=/run/current-system/sw/bin/bash -c '[[ $(($RANDOM % 10)) == 0 ]]'
ExecStart=/run/current-system/sw/bin/systemctl poweroff
  • Si la condición no se cumple, queda un mensaje más claro en el journal
May 05 11:05:32 diesel systemd[3117]: Condition check resulted in 1 in 10 chance to break your chains being skipped.
  • En general, aprovechar las opciones que ofrece systemd da una mejor experiencia que hacer todo manualmente con scripts
    • OnFailure= puede usarse para reaccionar cuando falla un script de servicio
    • Restart= puede usarse para intentar recuperarse de fallas transitorias

Enlace y ejecución de unidades temporizador

  • Si se coloca /etc/systemd/system/roulette.timer con la misma raíz de nombre, se puede enlazar el temporizador con roulette.service
[Unit]
Description=impending destruction

[Timer]
OnCalendar=10:00

[Install]
WantedBy=timers.target
  • Por defecto, la opción Unit= del temporizador selecciona la unidad de servicio con la misma raíz de nombre y sufijo .service
    • En este ejemplo, se selecciona roulette.service
    • Si se quiere ejecutar una unidad de servicio con otro nombre, se puede cambiar Unit=
  • El destino de ExecStart= no se ejecuta como comando de shell por defecto
    • Un destino con ruta absoluta debe tratarse como un script o como un intérprete que espera un script en forma de argumento de cadena
    • ExecStart=/usr/bin/echo Hello | /usr/bin/awk no funciona en este contexto porque la tubería no tiene significado aquí
  • Los argumentos de ExecStart= no heredan variables de entorno por defecto, salvo algunos valores predeterminados del administrador del sistema
    • El $PATH predeterminado está casi vacío
    • Ejecutar /usr/bin/env es una protección simple para poder usar elementos como systemctl
    • Si solo se hubiera usado ExecStart=/usr/bin/bash, $PATH sí incluiría entradas predeterminadas, pero usar env añade una capa extra de seguridad
  • El servicio puede ejecutarse directamente sin temporizador
systemctl start roulette
  • Un servicio sin sección [Install] no puede activarse con enable, y en esta estructura el temporizador es la forma estándar de ejecutar el servicio de manera consistente
  • systemctl actúa sobre roulette.service por defecto aunque no se escriba el sufijo explícito
  • Si se aplica systemctl start a una unidad .timer, el temporizador queda activo, pero no ejecuta de inmediato el servicio objetivo real de Unit=
systemctl start roulette.timer
  • status muestra cuándo será la siguiente ejecución del temporizador
systemctl status roulette.timer
Trigger: Sat 2026-04-18 10:00:00 MDT; 35min left
  • El flujo más simple consiste en crear el servicio objetivo, poner un temporizador con programación en la misma ubicación e iniciar el temporizador, no el objetivo
  • Si la sección [Install] del temporizador incluye WantedBy=, también se puede hacer que el temporizador se levante al arrancar el sistema
systemctl enable roulette.timer

Expresiones de tiempo: eventos de calendario y duraciones

  • En los temporizadores importa cómo se expresa la programación, y conviene distinguir entre intervalos repetitivos y eventos de calendario o marcas de tiempo
  • La página del manual systemd.time(7) tiene suficientes ejemplos y vale como primer material de referencia al escribir temporizadores
  • systemd-analyze puede validar y explicar expresiones de tiempo
systemd-analyze calendar '*-*-* *:*:*'
Normalized form: *-*-* *:*:*
    Next elapse: Sat 2026-04-18 16:44:26 MDT
       (in UTC): Sat 2026-04-18 22:44:26 UTC
       From now: 431ms left
  • Los temporizadores de systemd pueden definir no solo horas repetitivas basadas en reloj de pared, sino también duraciones repetidas a partir de algún evento previo, a diferencia del cron tradicional
  • La forma completa de daily significa ejecutar todos los años, todos los meses y todos los días a las 00:00:00
*-*-* 00:00:00
│ │ │ │  │  ╰── at second 00
│ │ │ │  ╰───── at minute 00
│ │ │ ╰──────── at hour 00
│ │ ╰────────── every day
│ ╰──────────── every month
╰────────────── every year
  • Se pueden usar abreviaturas como daily, la forma completa y otros valores soportados por systemd.time(7), y systemd-analyze sirve para comprobar los supuestos

Cuando conviene más una ejecución basada en eventos

  • En tareas reales, muchas veces encaja mejor “ejecutar después de otro evento” que “ejecutar todos los días a la misma hora”
  • Si una tarea vacía un directorio temporal, puede que haya muy poco que limpiar en /tmp si la expresión de cron ya pasó justo después del arranque
  • Expresarlo como “ejecuta una hora después de que arranque la computadora y luego cada hora” se alinea mejor con el comportamiento real del servicio y la lógica del calendario
[Timer]
OnBootSec=1h
OnUnitActiveSec=1h
  • OnBootSec=1h significa ejecutar una vez una hora después de iniciar la máquina
  • OnUnitActiveSec=1h significa volver a ejecutar una hora después de que se haya ejecutado Unit=, lo que hace que el temporizador se repita implícitamente
  • Este tipo de expresión periódica por duración suele encajar mejor para tareas de “ejecutar de vez en cuando” que expresiones como “ejecuta en este minuto de cada hora”
  • En el ejemplo de un bot de Slack que consulta la API de Advent of Code, la expresión */15 de cron cumple la política de la API de “cada 15 minutos”, pero si todos consultan igual, el tráfico puede concentrarse
  • Si tras modificar el código se inicia el temporizador y luego se ejecuta cada 15 minutos, se cumple el comportamiento necesario y además puede reducirse el problema de thundering herd

Ver el estado de los temporizadores de un vistazo

  • systemctl list-timers es un comando de alto nivel que resume el estado de los temporizadores en una máquina
systemctl list-timers
NEXT                                 LEFT LAST                                  PASSED UNIT                         ACTIVATES
Mon 2026-04-20 15:15:00 MDT      1min 40s Mon 2026-04-20 15:00:05 MDT        13min ago zfs-snapshot-frequent.timer  zfs-snapshot-frequent.service
Mon 2026-04-20 15:32:16 MDT         18min Mon 2026-04-20 14:22:15 MDT        51min ago fwupd-refresh.timer          fwupd-refresh.service
Mon 2026-04-20 16:00:00 MDT         46min Mon 2026-04-20 15:00:05 MDT        13min ago logrotate.timer              logrotate.service
Mon 2026-04-20 16:00:00 MDT         46min Mon 2026-04-20 15:00:05 MDT        13min ago zfs-snapshot-hourly.timer    zfs-snapshot-hourly.service
Tue 2026-04-21 00:00:00 MDT            8h Mon 2026-04-20 09:43:22 MDT     5h 29min ago zfs-snapshot-daily.timer     zfs-snapshot-daily.service
Tue 2026-04-21 07:31:28 MDT           16h Sun 2026-04-19 20:15:47 MDT           7h ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service
Mon 2026-04-27 00:00:00 MDT        6 days Mon 2026-04-20 09:43:22 MDT     5h 29min ago zfs-snapshot-weekly.timer    zfs-snapshot-weekly.service
Mon 2026-04-27 01:09:27 MDT        6 days Mon 2026-04-20 09:43:22 MDT     5h 29min ago fstrim.timer                 fstrim.service
Mon 2026-04-27 04:28:38 MDT        6 days Mon 2026-04-20 09:43:22 MDT     5h 29min ago zpool-trim.timer             zpool-trim.service
Fri 2026-05-01 00:00:00 MDT 1 week 3 days Wed 2026-04-01 10:07:51 MDT 1 week 1 day ago zfs-snapshot-monthly.timer   zfs-snapshot-monthly.service
Fri 2026-05-01 03:17:17 MDT 1 week 3 days Wed 2026-04-01 10:07:51 MDT 1 week 1 day ago zfs-scrub.timer              zfs-scrub.service

11 timers listed.
Pass --all to see loaded but inactive timers, too.
  • Con un solo comando se obtiene una vista completa de lo que se ejecuta según la programación de temporizadores
  • list-timers forma parte de la familia de subcomandos de systemd que se usan con frecuencia
    • list-units también es útil
    • list-paths es un subcomando agregado más recientemente a systemctl

Reactivar y ejecutar desde suspensión

  • WakeSystem= puede hacer que un temporizador cuyo tiempo se cumpla reactive el sistema desde suspensión
WakeSystem=
    Takes a boolean argument. If true, an elapsing timer will
    cause the system to resume from suspend, should it be
    suspended and if the system supports this.
...
  • Esta función es útil cuando hay que ejecutar un script importante sin depender de la acción física de que una persona abra la tapa de la laptop
  • En distribuciones como Arch o NixOS, que permiten descargar actualizaciones de paquetes antes de usarlas, se pueden traer los paquetes durante la noche y actualizarlos por la mañana ya frente al teclado
  • El manual indica que, si se quiere volver a suspender el sistema después de que termine la .service, hay que hacerlo manualmente

Distribuir la hora de ejecución y mitigar el thundering herd

  • El problema de thundering herd es un problema del sistema que ocurre cuando muchos procesos despiertan al mismo tiempo
  • Si todos los sistemas Debian del mundo tuvieran apt update fijado a las 00:00:00, la medianoche sería un pésimo pico de tráfico para todos
  • FixedRandomDelay= y RandomizedOffsetSec= ayudan a distribuir los tiempos de ejecución
FixedRandomDelay=
    Takes a boolean argument. When enabled, the randomized delay
    specified by RandomizedDelaySec= is chosen deterministically,
    and remains stable between all firings of the same timer,
    even if the manager is restarted. ...

RandomizedOffsetSec=
    Offsets the timer by a stable, randomly-selected, and evenly
    distributed amount of time between 0 and the specified time
    value. ...
  • Estas opciones pueden usarse en sistemas reales que revisan actualizaciones de software
  • Repartir las ejecuciones con distribución uniforme ayuda a reducir el problema de thundering herd, mantener un comportamiento consistente y evitar interferencias como reinicios de demonios mientras se coordinan servicios distribuidos
  • En general, las opciones de temporización son muy configurables y ofrecen un control fino

Compensar de inmediato ejecuciones perdidas

  • Persistent= es especialmente adecuado para scripts programados que no deberían omitirse por culpa de una laptop suspendida, pero que tampoco necesitan llegar al extremo de WakeSystem=
Persistent=
    Takes a boolean argument. If true, the time when the service
    unit was last triggered is stored on disk. When the timer is
    activated, the service unit is triggered immediately if it
    would have been triggered at least once during the time when
    the timer was inactive. ...
  • Si un sistema con check-ins programados de gestión de configuración sufrió tiempo fuera de servicio, basta con poner Persistent= en el .timer para converger al estado correcto apenas vuelva en línea
  • Sin Persistent=, puede tocar esperar hasta la siguiente hora normal de ejecución del temporizador, y ese tiempo podría ser largo
  • Otros trabajos donde no conviene esperar al detectar una activación perdida incluyen actualizaciones del sistema y verificación de tareas por lotes

Puntos a cuidar al escribir temporizadores

  • Los temporizadores en el contexto del administrador de usuario que se manejan con systemctl --user también son válidos, pero hay que fijarse bien en el destino usado en [Install]
  • Según la distribución, el destino apropiado para temporizadores de usuario puede ser default.target
  • Igual que con cron, sigue aplicando la advertencia general de mantener un reloj del sistema preciso
  • Los usuarios de systemd pueden revisar el estado de sincronización con timedatectl timesync-status
  • Muchos editores ya soportan de forma nativa el formato de archivos de unidad de systemd, lo que ayuda cuando los archivos crecen
  • En Emacs se puede usar el paquete emacs systemd

2 comentarios

 
GN⁺ 2026-06-02
Comentarios de Hacker News
  • No he usado lo suficiente los temporizadores de systemd como para rebatirlo con firmeza, pero no termino de entender eso de que el $PATH de cron es ambiguo
    Puedes configurar PATH directamente dentro del crontab, y no veo por qué sería menos predecible que algo definido en sitios como /etc/bashrc, ~/.bashrc, ~/.profile, ~/.bash_profile, /etc/systemd/…
    Uso Linux desde 1994, pero no me sé de memoria la sintaxis de cron. Aun así, en los comentarios del crontab ya viene escrito m h dom mon dow command, así que solo hay que poner los números según el encabezado
    Entiendo las demás quejas y, la próxima vez que necesite una tarea programada con cron, pienso probar con un temporizador de systemd

    • Eso de “solo hay que poner los números según el encabezado” no resume de forma justa la crítica original, porque esa no es toda la sintaxis
      Hay comas, barras, asteriscos y combinaciones, y si necesitas aleatorización, por lo general cron no puede hacerlo por sí solo, así que hay que meterlo dentro del comando. Escribir una expresión de cron que no sea trivial no es fácil
    • Como alguien que ha trabajado con aplicaciones que admiten expresiones cron, los números son apenas la parte más básica del lenguaje
      Cuando alguien pone algo como 5,3/4 4-8,11 1 4,5,6,9-11 */2, luego toca divertirse haciendo ingeniería inversa para entender qué quiso decir en realidad, y normalmente no significa lo que escribió
      Si además le sumas extensiones que solo se admiten en algunos entornos cron, se vuelve todavía más complejo
      Los temporizadores de systemd me resultaron mucho más fáciles de administrar. Poder controlar si se permite la ejecución duplicada de tareas largas, o ejecutar una tarea dentro de una ventana de inicio-fin en vez de a una hora fija, es una gran mejora
      Una vez una tarea de respaldo cayó en un bucle de enlaces simbólicos y tiró mi VPS; cron siguió lanzando nuevos respaldos aunque el anterior no hubiera terminado
      También era molesto tener que reescribir comandos y scripts por el PATH especial de CRON, aunque algo parecido también puede pasar con algunos temporizadores de systemd. Aun así, puedes ejecutar el temporizador manualmente sin tener que cambiar el crontab para que corra 30 segundos después y esperar
    • No quiero probar tareas de cron dejando $PATH hardcodeado en el crontab
      Si no lo hardcodeas, el $PATH que usa cron al ejecutar será distinto del $PATH con el que pruebas el comando manualmente. systemctl start foo.service inicia el comando en el mismo entorno en el que se iniciaría cuando dispare el temporizador, así que puedes saber si va a comportarse igual
      En cambio, una tarea de cron se ejecuta a la hora indicada en el crontab. Los temporizadores de systemd por lo general sí disparan a la hora indicada, pero por errores lógicos de systemd puede pasar que se ejecuten una vez el 29 de febrero y luego no vuelvan a ejecutarse nunca, o que al “reiniciar” la unidad del temporizador se disparen o no
    • La ventaja del entorno de systemd es que es estándar y casi vacío. En cambio, el entorno del crontab es completamente distinto del que heredan scripts de supervisord o sysvinit, y eso me ha pegado muchas veces
      En systemd no hay esa brecha, porque sin importar qué lo dispare, la unidad que realmente se ejecuta es la misma
      Igual hay que saber cuál es el entorno base, pero es un entorno casi limpio y no afectado por el shell. Yo lo veo como una ventaja de systemd
    • No diría exactamente que PATH sea ambiguo, pero cron sí tiene problemas relacionados con PATH
      En el valor predeterminado faltan rutas que uno esperaría, como /usr/local/bin o /usr/sbin para root, y algunas distribuciones como Arch Linux ni siquiera indican la ruta por defecto o una recomendación de configuración en la página del manual
      Si quieres agregar una ruta solo para un script específico, tienes que envolverlo con env, configurarlo en un script wrapper, o cambiar la ruta antes de la entrada y luego revertirla después
      No puedes usar ~ ni $HOME dentro de PATH, y tienes que escribir la ruta absoluta completa, lo que es especialmente molesto en crontabs de usuario
      No es difícil buscarle la vuelta, pero en general los temporizadores de systemd, que por defecto usan las mismas rutas que otros servicios, ofrecen una mejor experiencia
  • Me cambié de cronie a temporizadores de systemd porque son más flexibles con la hora de arranque del sistema
    Mi estrategia de respaldo consiste en crear todos los días una entrada de archivo borg a una hora fija, pero con cronie el sistema tiene que estar encendido en ese momento programado. Los temporizadores de systemd toleran esa situación y ejecutan el servicio en cuanto el sistema vuelve a estar disponible
    El repositorio de automatización de respaldos es https://github.com/gchamon/borg-automated-backups

    • Cronie tiene un mecanismo para eso llamado anacron. En mi sistema, cron llama cada hora a /etc/cron.hourly/0anacron y ejecuta las tareas de /etc/cron.{daily,weekly,monthly} aunque se haya pasado la hora de ejecución más temprana. También se puede configurar un retraso aleatorio
      Si editas /etc/anacrontab, puedes crear horarios personalizados
      A nivel de usuario, supongo que podrías poner una entrada como @hourly anacron -t /path/to/anacrontab -S /path/to/spooldir en tu crontab de usuario, aunque no lo he probado personalmente
      Muchas implementaciones de cron también tienen mecanismos similares
    • cron tiene la opción @reboot, y la uso en algunos scripts; funciona bien
    • ¿Cronie no tiene un metadisparador @reboot?
  • No me convencen las boquillas de las impresoras Canon: si quedan sin uso un tiempo, se pueden tapar. Así que le hice a Claude que generara un script de systemd para imprimir una foto de perrito cada semana, asegurándome de que tuviera suficiente espectro CMYK como para exigirle a la impresora
    Cada lunes, sentarme en el escritorio y que de repente salga una foto de la impresora es una sorpresa bastante agradable

    • Estaría bueno que, en vez de desperdiciar tinta vaciándola en una esponja cada pocos días, la impresora tuviera un modo para imprimir imágenes aleatorias de un álbum o calendario
      Como mínimo, podría servir como idea de proyecto para una feria de ciencias infantil
    • Mi padre tenía un modelo parecido a la Deskjet 720
      Tras su fallecimiento, estuvo varios años sin usarse y hasta desconectada; cuando necesité imprimir en color, solo la enchufé y la puse a imprimir
      Hacia el 20% de la página 1 ya habían vuelto todos los colores, y después imprimió unas 20 páginas sin problemas
    • Hice algo parecido en mi primer año de universidad con una vieja Samsung ML-2010
      Parecía más un problema de software que de hardware: si la impresora se quedaba conectada a la computadora sin usarse por más de una semana, simplemente dejaba de imprimir
      Podría haber investigado los logs, pero en su lugar armé una tarea de cron para imprimir una página de prueba los lunes y jueves. Arriba de la página de prueba solo decía algo como LOL PRINTER WORKS
      En realidad no era tanto desperdicio. Llevaba muchas materias de matemáticas, así que necesitaba muchísimo papel por una sola cara para resolver ejercicios; primero usaba impresiones fallidas o de prueba y después recién hojas en blanco
    • La respuesta es una impresora láser. Solo con el ahorro en consumibles ya se paga sola
    • Iba a recomendar una impresora color LED barata de OKI, pero se retiraron del mercado de consumo
      Aunque la resolución máxima era apenas de 600dpi, los colores eran muy buenos y uniformes, y que el tóner no se secara era el criterio clave de compra para mi hermano. Las inkjet de HP se le taparon varias veces
  • Me encantan los temporizadores de systemd. Poco a poco fui migrando todas las tareas de cron que desplegaba con Ansible a temporizadores, y ahora solo tengo que copiar con Ansible
    La integración con journalctl está especialmente buena, y todavía más en sistemas operativos modernos donde ya no hay syslog, como Debian 13. También es cómodo poder iniciar manualmente el servicio para depurar
    Las tareas de cron que no funcionan eran una molestia porque había que copiar y pegar o usar scripts de shell extra, por no hablar del agujero negro donde desaparece la salida estándar de los trabajos de cron
    También puedes monitorearlos como cualquier servicio de systemd y recibir alertas cuando fallan. Me parece bien que cada vez más proyectos open source recomienden temporizadores como método de despliegue

    • Está bien que un proyecto recomiende temporizadores, pero para quedar satisfecho necesito poder ignorarlo y usar cron si quiero
  • NixOS usa systemd por defecto, así que lo trata como un componente de primera clase para la administración. Se aprecia todavía más si vienes de usar launchd en macOS
    También me gusta que, al distribuir herramientas para NixOS, se pueda aprovechar systemd de forma natural en vez de usarlo como un parche agregado encima
    Aun así, si distribuyera una herramienta con mucha gestión de ciclo de vida para todos los usuarios de Linux, me pregunto qué haría, porque systemd no está en todas partes
    Corro el scrub mensual de mi pool de btrfs con un temporizador de systemd. Es bastante útil poder decidir si, cuando el usuario inicia un scrub manualmente, se salta la siguiente ejecución programada, o si una tarea mensual debe acumularse cuando la máquina estuvo apagada 6 meses o condensarse en una sola ejecución

    • En NixOS, las tareas de systemd son realmente fáciles. Es mejor definir las unidades en Nix que pelearse con archivos INI
      systemd.services.sync-recyclarr = { serviceConfig.Type = "oneshot"; path = [ pkgs.podman ]; script = '' podman exec -it recyclarr recyclarr sync radarr podman exec -it recyclarr recyclarr sync sonarr ''; };
      systemd.timers.sync-recyclarr = { timerConfig = { OnCalendar = "daily"; Persistent = true; Unit = "sync-recyclarr.service"; }; partOf = [ "sync-recyclarr.service" ]; requires = [ "podman-recyclarr.service" ]; wantedBy = [ "timers.target" ]; };
    • Me pregunto si lo defines directamente dentro del archivo flake.nix
      Yo también uso NixOS, pero mantengo toda mi configuración en el formato original y solo le creo enlaces simbólicos con Nix. Así puedo reutilizar fácilmente la configuración también en sistemas que no son NixOS
      El problema es que NixOS no parece detectar ni ejecutar los temporizadores y servicios de systemd que pongo en la carpeta ~/.config/systems/user, y cosas como WantedBy=default.target tampoco hacen efecto
      Por eso, una vez que reinicio manualmente todos los servicios después de reiniciar la máquina, termino coincidiendo en que los temporizadores de systemd son geniales
  • Los temporizadores no solo funcionan con unidades de servicio del mismo nombre; también pueden trabajar con unidades arbitrarias, así que son sorprendentemente flexibles
    En mi servidor hay un temporizador que inicia backup.target, el cual ejecuta todo el ciclo de backup con restic backup, restic prune y restic forget, con una hora de inicio aleatoria cada mañana e incluyendo notificaciones
    Las unidades reales restic-* son Quadlets de Podman, así que mientras el servidor tenga Podman y Systemd, la configuración funciona sin depender del contenido del servidor
    Eso sí, los temporizadores son de los tipos de unidad de systemd más toscos para el uso cotidiano. Entiendo por qué están separados en dos archivos y por qué la sintaxis de start y enable es distinta, pero a veces uno solo quiere crear un archivo, ejecutar un script y listo

    • Uso una configuración parecida para backups. A veces desactivé el temporizador porque quería hacer otras tareas con el repositorio de restic, como limpiar locks, y me llevé la sorpresa de que una unidad ya disparada seguía corriendo
    • Parece que hace falta una capa de abstracción más encima de las unidades de systemd. Algo así como una herramienta declarativa de línea de comandos que se encargue, en vez de editar archivos directamente
      En la era de los LLM quizá no sea un gran problema, pero igual se siente un poco tedioso cada vez
    • Me pregunto por qué aleatorizas el horario del backup
  • No siempre me han encantado todas las partes de systemd, pero en general coincido con esta opinión
    Para tareas programadas a nivel de “sistema”, casi dejé por completo de usar cron y terminé prefiriendo los timers de systemd. Para programación dentro del ámbito de una aplicación específica, también podría usar algo como Quartz
    La razón es difusa y difícil de explicar, pero la forma de systemd encaja más limpiamente con mi modelo mental de “así es como deberían funcionar las cosas”. En el pasado también me tocó varias veces lidiar con ejecuciones de scripts en cron donde PATH era ambiguo y eso hacía todo impredecible, aunque no es solo por eso
    No diría que los timers de systemd sean universal u objetivamente mejores que cron, pero al menos conmigo sí lograron convencerme

  • Fue una excelente introducción a los timers de systemd, y de hecho me convenció lo suficiente como para por fin probarlos
    También me gusta list-timers. Con cron no era fácil tener una vista completa de todos los trabajos que corrían en una máquina. Había que revisar el crontab de cada usuario, /etc/cron.d/ y los directorios daily/hourly/monthly
    De hecho tengo un caso de uso que necesita ejecutarse una vez unos 5 minutos después del arranque y luego aproximadamente cada 12 horas, y me gusta saber que los timers de systemd pueden encargarse de eso

    • Gracias por las palabras amables. En una situación donde systemd se usa tanto como ahora, realmente siento que vale la pena aprender a usar herramientas como systemd-analyze y systemctl list-timers
  • systemd parece complejo al principio, pero una vez que lo usas ya no quieres usar otra cosa. Es cómodo administrar todo con systemctl

    • Todavía hay decisiones extrañas en el diseño que no termino de entender
      Por ejemplo, no entiendo por qué la definición de unidades tiene que ser necesariamente un archivo real en disco. Cuando el daemon vuelve a leer la configuración, relee todos los archivos, no solo los que cambiaron. Me hace pensar que debería existir una API para agregar unidades de forma programática. Hay cosas parecidas, pero tienen muchas limitaciones y no son flexibles
      También me parece raro que no se puedan declarar varias unidades dentro de un solo archivo. El hecho de que esté diseñado alrededor del sistema de archivos y que no haya hecho abstracciones a otro nivel no me parece una decisión particularmente inteligente. Tampoco diría que siga la filosofía Unix
      Y en cuanto al formato de definición de unidades, si TOML hubiera existido en ese momento, ojalá hubieran usado algo más razonable
    • systemd sí tiene páginas de manual que realmente son útiles
    • Hay quienes lo ven distinto. Lo prueban y luego no quieren volver a usarlo. Yo odio systemd de verdad
      Aunque claro, supongo que es porque ya estoy viejo. Obviamente systemd-* es el único camino correcto y cualquiera que piense distinto seguro es un opinólogo
    • Todavía odio el logging de journald
    • Es una postura bastante moderna. Cuando systemd apareció por primera vez, la gente realmente lo odiaba, pero a mí siempre me gustó y pensaba que al final la gente lo iba a aceptar. Me da gusto ver que de verdad terminó pasando
  • Llevo más de 20 años usando Linux y más de 10 usando systemd
    Y aun así siempre hay algo nuevo que aprender, y de hecho ahora lo considero otra herramienta útil más

    • Llevo como 30 años usando Linux y, apparently, al parecer todos estuvimos equivocados durante décadas por usar cron
 
GN⁺ 2026-06-02
Comentarios de Lobste.rs
  • systemd no es perfecto, pero da la impresión de que muchas decisiones de diseño se basan en lecciones aprendidas de enfoques más tradicionales del pasado.
    Hace poco volví a escuchar este episodio de CRE de 2015 en el que Lennart Poettering explica ese contexto, y todavía vale la pena recomendarlo.

  • Soy de los que no soportan systemd hasta la médula, pero creo que systemd.timers es una de las ideas “menos malas” de este producto.
    Por eso me sorprendió un poco que el autor lo defendiera desacreditando a gente con quejas válidas.
    Aun así, me gusta usarlo junto con el comando at. Para comandos que deben ejecutarse una sola vez en un momento específico, uso at; para lo demás, temporizadores de systemd y archivos de unidad simples.
    La mejora que más me gustaría ver es poder saber qué usuario está ejecutando un temporizador. Soy uno de los pocos que todavía administran una shell box en 2026, pero sería útil poder identificar qué usuario creó el temporizador que está golpeando el disco cada segundo.

    • Para ese propósito, quizá se podrían usar unidades de usuario en vez de hacer que todos instalen temporizadores del sistema.
      Según entiendo, con loginctl enable-linger pueden ejecutarse incluso sin una sesión de usuario activa. Claro, habrá casos de uso donde eso no sea suficiente, y no conozco la situación concreta.
  • Ojalá los temporizadores de systemd tuvieran una barrera de entrada más baja, sobre todo del lado de la administración de usuarios.
    Viendo la cantidad de configuración necesaria, de verdad es difícil ganarle a crontab -e.

    • La forma de systemd, que exige varios archivos de configuración y servicios para definir un solo temporizador... como elección de API no tiene ningún sentido.
  • Pasé mucho tiempo pensando cómo recopilar de forma ordenada los logs de scripts de cron, hasta que me di cuenta de que simplemente podía usar temporizadores de systemd.
    El problema del logging quedó resuelto. Ya no tengo motivo para volver a usar cron, y ojalá lo hubiera sabido antes.

    • ¿No basta con canalizarlo a logger, agregarlo a un archivo de log con >>, o dejarlo con la configuración por defecto y recibir correos?
  • Llámenme anticuado, pero todavía tengo configurado el correo electrónico para que el servidor me contacte.
    Si lo automatizas, viene gratis en cada host nuevo, y en el día a día sigue siendo bastante conveniente.
    Por ejemplo, abro un multiplexor, ejecuto long_running_process | mail root@localhost -s "done $?" y luego me olvido del asunto.

  • Buen artículo; yo también tenía un borrador de algo parecido y hace poco tuve que volver a consultarlo.
    Si, como yo, te metes en la madriguera de conejo de systemd, recomiendo dejar los archivos de unidad y los temporizadores del proyecto correspondiente como enlaces simbólicos en /etc/systemd/system/.
    Una queja que tengo sobre systemd es que no distingue entre las unidades instaladas por la distribución y las que escribiste tú mismo, pero con enlaces simbólicos puedes mantener esa separación por tu cuenta.

    • En realidad, esa distinción la maneja la ruta.
      Las unidades del sistema/paquete/distribución van en /usr/lib/systemd/system, y los overrides locales o unidades locales van en /etc/systemd/system.