systemd (Español)/Timers (Español)
Los temporizadores son archivos de unidad de systemd (Español) cuyo nombre termina en .timer
que controlan archivos .service
o eventos. Los temporizadores se pueden usar como una alternativa a cron (lea #Como un reemplazo de cron). Los temporizadores tienen soporte incorporado para ejecutar eventos basados en el calendario, eventos de tiempo monotónicos y se pueden ejecutar de forma asíncrona.
Unidades de temporizador
Los temporizadores son archivos de unidades de systemd terminados en un sufijo .timer
. Los temporizadores son como cualquier otro arcivo de configuración de unidad y se cargan desde las mismas rutas, pero incluyen una sección [Timer]
que define cuándo y cómo se activa el temporizador. Los temporizadores se definen como uno de estos dos tipos:
- Temporizadores en tiempo real (también conocido como «wallclock timers») se activan con un evento del calendario, de la misma manera que lo hacen los cronjobs. La opción
OnCalendar=
se utiliza para definirlos. - Temporizadores monotónicos se activan después de un intervalo de tiempo condicionado a un punto de inicio variable. Se detienen si el equipo está temporalmente suspendido o apagado. Hay varios temporizadores monotónicos diferentes, pero todos tienen la forma:
OnTypeSec=
. Los temporizadores monotónicos comunes incluyenOnBootSec
yOnActiveSec
.
Para obtener una explicación completa de las opciones del temporizador, consulte systemd.timer(5). La sintaxis de los argumentos para los eventos del calendario y los intervalos de tiempo se definen en systemd.time(7).
Unidad de servicio
Para cada archivo .timer
, existe un archivo .service
coincidente (por ejemplo, foo.timer
y foo.service
). El archivo .timer
activa y controla el archivo .service
. El archivo .service
no requiere una sección [Install]
ya que son las unidades de temporizador las que se activan. Si es necesario, es posible controlar una unidad con un nombre diferente usando la opción Unit=
en la sección [Timer]
del archivo temporizador.
Gestión
Para usar una unidad temporizador active e inicie la misma como cualquier otra unidad (recuerde agregar el sufijo .timer
). Para ver todos los temporizadores iniciados, ejecute:
$ systemctl list-timers
NEXT LEFT LAST PASSED UNIT ACTIVATES Thu 2014-07-10 19:37:03 CEST 11h left Wed 2014-07-09 19:37:03 CEST 12h ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service Fri 2014-07-11 00:00:00 CEST 15h left Thu 2014-07-10 00:00:13 CEST 8h ago logrotate.timer logrotate.service
- Para enumerar todos los temporizadores (incluido inactivos), use
systemctl list-timers --all
. - El estado de un servicio iniciado por un temporizador probablemente aparecerá inactivo a menos que se esté activando en ese momento.
- Si un temporizador se desincroniza, puede ayudar eliminar su archivo
stamp-*
en/var/lib/systemd/timers
(o~/.local/share/systemd/
en caso de temporizadores de usuario). Estos son archivos de longitud cero que marcan la última vez que se ejecutó cada temporizador. Si se eliminan, se reconstruirán en el próximo inicio de su temporizador.
Ejemplos
Un archivo de unidad de servicio se puede programar con un temporizador listo para usar. Los siguientes ejemplos programan que el servicio, foo.service
, se ejecutará con el temporizador correspondiente llamado foo.timer
.
Temporizador monotónico
Un temporizador que se iniciará 15 minutos después del arranque y nuevamente cada semana mientras el sistema se está ejecutando.
/etc/systemd/system/foo.timer
[Unit] Description=Run foo weekly and on boot [Timer] OnBootSec=15min OnUnitActiveSec=1w [Install] WantedBy=timers.target
Temporizador en tiempo real
Un temporizador que comienza una vez a la semana (a las 12:00 AM del lunes). Cuando se activa, activa el servicio inmediatamente si se perdió la última hora de inicio (opción Persistent=true
), por ejemplo, debido a que el sistema estaba apagado:
/etc/systemd/system/foo.timer
[Unit] Description=Run foo weekly [Timer] OnCalendar=weekly Persistent=true [Install] WantedBy=timers.target
Cuando se requieren fechas y horas más específicas, los eventos de OnCalendar
utilizan el siguiente formato:
DayOfWeek Year-Month-Day Hour:Minute:Second
es decir:
DíadelaSemana Año-Mes-Día Hora:Minuto:Segundo
Se puede usar un asterisco para especificar cualquier valor y se pueden usar comas para listar posibles valores. Dos valores separados por ..
indica un rango contiguo.
En el ejemplo siguiente, el servicio se ejecuta los primeros cuatro días de cada mes a las 12:00 PM, pero solo si ese día es lunes o martes.
OnCalendar=Mon,Tue *-*-01..04 12:00:00
Para ejecutar un servicio el primer sábado de cada mes, use:
OnCalendar=Sat *-*-1..7 18:00:00
Al usar DayOfWeek
, se debe especificar, al menos, un día de la semana. Si quiere algo para ejecutar todos los días a las 4 AM, utilice:
OnCalendar=*-*-* 4:00:00
Para ejecutar un servicio en diferentes momentos, OnCalendar
puede especificarse más de una vez. En el siguiente ejemplo, el servicio se ejecuta a las 22:30 los días entre fines de semana y a las 20:00 los fines de semana.
OnCalendar=Mon..Fri 22:30 OnCalendar=Sat,Sun 20:00
Dispone de más información en systemd.time(7).
OnCalendar
se puede probar para verificar su funcionamiento y para calcular la próxima vez en que se producirá la condición suspensiva para el caso de que se utilice una unidad de temporizador concalendar
de la utilidad systemd-analyse. Por ejemplo, se puede usarsystemd-analyze calendar weekly
osystemd-analyze calendar "Mon,Tue *-*-01..04 12:00:00"
.- La orden
faketime
es especialmente útil para probar varios escenarios con la orden anterior; viene con el paquete libfaketime. - Expresiones de eventos especiales como
daily
yweekly
hacen referencia a horas de inicio específicas y, por lo tanto, cualquier temporizador que comparta dichos eventos de calendario se iniciará simultáneamente. Los temporizadores que comparten eventos de inicio pueden provocar un rendimiento deficiente del sistema si los servicios de los temporizadores compiten por los recursos del sistema. La opciónRandomizedDelaySec
en la sección[Timer]
evita este problema al alternar aleatoriamente la hora de inicio de cada temporizador. Vea systemd.timer(5).
Unidades .timer transitorias
Se puede utilizar systemd-run
para crear unidades .timer
transitorias. Es decir, se puede configurar una orden para que se ejecute a una hora específica sin tener un archivo de servicio. Por ejemplo, la siguiente orden muestra un archivo después de 30 segundos:
# systemd-run --on-active=30 /bin/touch /tmp/foo
También se puede especificar un archivo de servicio preexistente que no tiene un archivo de temporizador. Por ejemplo, lo siguiente inicia la unidad systemd llamada someunit.service
después de que hayan transcurrido 12 horas y media:
# systemd-run --on-active="12h 30m" --unit someunit.service
Véase systemd-run(1) para más información y ejemplos.
Como un reemplazo de cron
Aunque cron es posiblemente el planificador de trabajos más conocido, los temporizadores de systemd pueden ser una alternativa.
Beneficios
Los principales beneficios de usar temporizadores provienen del hecho de que cada trabajo tiene su propio servicio systemd. Algunos de estos beneficios son:
- Los trabajos pueden iniciarse fácilmente independientemente de sus temporizadores. Esto simplifica la depuración de errores.
- Cada trabajo puede configurarse para ejecutarse en un entorno específico (consulte systemd.exec(5)).
- Los trabajos se pueden adjuntar a grupos de control.
- Los trabajos se pueden configurar para que dependan de otras unidades de systemd.
- Los trabajos se registran en el journal de systemd para una fácil depuración de errores.
Advertencias
Algunas cosas que son fáciles de hacer con cron son difíciles de hacer solo con unidades de temporizador:
- Creación: para configurar un trabajo temporizado con systemd necesita crear dos archivos y ejecutar órdenes
systemctl
, en comparación con crontab que basta con agregar una sola línea. - Correos electrónicos: no hay un equivalente incorporado a
MAILTO
de cron para enviar correos electrónicos en el caso de que falle el trabajo. Consulte la siguiente sección para ver un ejemplo de cómo configurar una funcionalidad similar utilizandoOnFailure=
.
MAILTO
Puede configurar systemd para enviar un correo electrónico cuando falla una unidad. Cron envía un correo a MAILTO
si el trabajo da una salida stdout o stderr, aunque muchos trabajos se pueden configurar para generar solo un error. Primero, necesita dos archivos: un ejecutable para enviar el correo y un .service para iniciar el ejecutable. Para este ejemplo, el ejecutable es solo un script de intérprete de órdenes que usa sendmail
:
/usr/local/bin/systemd-email
#!/bin/bash /usr/bin/sendmail -t <<ERRMAIL To: $1 From: systemd <root@$HOSTNAME> Subject: $2 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 $(systemctl status --full "$2") ERRMAIL
Cualquiera que sea el ejecutable que utilice, probablemente debería tomar, al menos, dos argumentos, como lo hace este script de intérprete de órdenes: la dirección a la que enviar el correo y el archivo de la unidad para obtener el estado (de no entregado). El .service que creamos pasará estos argumentos:
/etc/systemd/system/status-email-user@.service
[Unit] Description=status email for %i to user [Service] Type=oneshot ExecStart=/usr/local/bin/systemd-email address %i User=nobody Group=systemd-journal
Donde user
es el usuario que recibe el correo electrónico y address
es la dirección de correo electrónico de ese usuario. Aunque el receptor esté codificado, el archivo de unidad sobre el que se informa se pasa como un parámetro de instancia, por lo que este servicio puede enviar correo electrónico para muchas otras unidades. En este punto, puede iniciar status-email-user@dbus.service
para verificar que puede recibir los correos electrónicos.
Luego simplemente edite el servicio para el que desea correos electrónicos y agregue OnFailure=status-email-user@%n.service
a la sección [Unit]
. %n
pasa el nombre de la unidad a la plantilla.
- Si configura la seguridad sSMTP de acuerdo con sSMTP#Security, el usuario
nobody
no tendrá acceso a/etc/ssmtp/ssmtp.conf
, y la ordensystemctl start status-email-user@dbus.service
fallará. Una solución para ello es usarroot
como User en la unidadstatus-email-user@.service
. - Si intenta utilizar
mail -s somelogs address
en su script de correo electrónico,mail
se bifurcará y systemd interrumpirá el proceso de correo cuando vea su script salir. Haga que el correo no se bifurque conmail -Ssendwait -s somelogs address
.
Utilizar un crontab
Se pueden solucionar varias de las advertencias descritas arriba mediante la instalación de un paquete que pase un crontab tradicional para configurar los temporizadores. systemd-cron-nextAUR[enlace roto: package not found] y systemd-cronAUR son dos de estos paquetes. Estos pueden proporcionar la característica MAILTO
que falta.
Además, al igual que con crontabs, se puede obtener una vista unificada de todos los trabajos programados con systemctl
. Véase #Gestión.
Véase también
- systemd.timer(5)
- Página wiki del Proyecto Fedora sobre los temporizadores basados en el calendario de systemd
- Sección de la wiki de Gentoo sobre los servicios temporizadores de systemd
- systemd-cron-next — herramienta para generar temporizadores/servicios desde archivos crontab y anacrontab
- https://github.com/systemd-cron/systemd-cron-next || systemd-cron-nextAUR[enlace roto: package not found]
- systemd-cron — proporciona unidades systemd para ejecutar scripts de cron; utilizando systemd-crontab-generator para convertir crontabs