Aplazar una tarea hasta un momento concreto en Ubuntu Server 20.04 LTS

Publicado por P. Ruiz en

Cuando administramos un sistema, es fundamental poder aplazar tareas para ejecutarlas automáticamente cuando pase un tiempo. Esto nos permite ejecutar un script de mantenimiento, realizar una copia de seguridad de una base de datos o incluso apagar el equipo en el momento que elijamos del futuro.

Es importante aclarar que el objetivo no es crear tareas repetitivas que se ejecuten en periodos concretos, como hemos aprendido a realizar en otros artículos  con cron o anacron. En este caso, el objetivo es ejecutar un comando, una vez, como si lo fuésemos a hacer en este momento, pero retrasando su ejecución a un momento determinado.

Si lo que pretendes es realizar tareas repetitivas, puedes consultar los siguientes artículos publicados también en SomeBooks.es:

Cómo utilizar at

Cuando ejecutamos el comando at se pone en funcionamiento el servicio atd que controlará el momento exacto en el que se ejecutará el comando que le hayamos indicado.

El artículo de hoy lo hemos desarrollado sobre Ubuntu Server pero, para ponerlo en práctica sobre la versión de escritorio, solo tienes que abrir una ventana de terminal. Por ejemplo, usando la combinación de teclas Alt + Control + T.

El comando at guarda los valores de las variables de entorno y el directorio actual. Cuando llegue el momento de ejecutar la tarea utilizará los valores guardados, de modo que no le afecten los cambios que se produzcan después de programarla.

Por ejemplo, si quiero que se ejecute una tarea cualquiera, de forma automática, a las 19:37, sólo tendría que escribir en la consola una orden como esta:

at 19:37

Escribimos el comando y pulsamos la tecla Intro.

Aplazar-una-tarea-hasta-un-momento-concreto-en-Ubuntu-Server-20-04-LTS-001

Veremos que aparece un prompt específico de at donde escribimos los comandos que queramos que se ejecuten.

También recibimos un aviso informando de que at utiliza el intérprete de comandos /bin/sh.

Aplazar-una-tarea-hasta-un-momento-concreto-en-Ubuntu-Server-20-04-LTS-002

Cuando escribamos el nombre de más de un comando o programa, como haremos en este ejemplo, debemos saber que no se iniciará la ejecución del segundo comando mientras se esté ejecutando el primero (aunque haya pasado el momento en el que debería iniciarse). La intención de este comportamiento es que podamos programar tareas que estén formadas por varias subtareas que deban ejecutarse por orden.

Si necesitamos que varias tareas inicien su ejecución de forma simultánea, sólo tendremos que ejecutar at varias veces.

A modo de ejemplo, comprobaremos cómo funciona at consiguiendo que, a la hora indicada, se muestre el contenido del directorio actual (que es el directorio de trabajo de la cuenta). A continuación, ejecutaremos el script que usábamos en el artículo dedicado a anacron (Programar tareas asíncronas en Ubuntu Server 20.04 LTS) y, por último, volvemos a mostrar el contenido de la carpeta. De este modo, comprobaremos que el script se ha ejecutado correctamente.

En definitiva, algo como esto:

ls -l > /dev/tty1
./prueba.sh
ls -l > /dev/tty1

Observa que hemos incluido cada comando en una línea independiente.

Aplazar-una-tarea-hasta-un-momento-concreto-en-Ubuntu-Server-20-04-LTS-003

Como estamos usando el script que creamos en el artículo Programar tareas asíncronas en Ubuntu Server 20.04 LTS, hemos tenido que cambiar sus permisos para poder ejecutarlo con los privilegios de una cuenta normal. Esto puedes conseguirlo, por ejemplo, escribiendo:

sudo chmod 777 prueba.sh

Aunque también podríamos haber ejecutado at con privilegios administrativos anteponiendo la orden sudo.

Cuando hayamos terminado de escribir, pulsamos la combinación de teclas Ctrl + D. En la pantalla aparecerá la marca <EOT>.

También nos informa del momento exacto en el que se ejecutará la tarea.

Aplazar-una-tarea-hasta-un-momento-concreto-en-Ubuntu-Server-20-04-LTS-004

Cuando aplazamos tareas, no es frecuente que necesitemos obtener resultados en la pantalla. De hecho, tal y como hemos dicho más arriba, incluso puede haber cambiado el contexto de la cuenta de usuario.

Por ese motivo, de forma predeterminada, el comando at envía tanto la salida estándar como la salida de error al correo, usando el comando /usr/sbin/sendmail.

Por ese motivo, si no obtenemos los resultados esperados, es buena idea comprobar el contenido del spool local de correo (/var/spool/mail/$USER) o, incluso, sus archivos log.

Como en nuestro ejemplo sí necesitábamos salida en pantalla, hemos optado por redirigir el resultado del comando a la pantalla predeterminada, que en mi caso es /dev/tty1.

Si necesitas saber el valor para tu sistema, puedes usar el comando tty.

Basta con escribir el nombre del comando y pulsar la tecla Intro.

Aplazar-una-tarea-hasta-un-momento-concreto-en-Ubuntu-Server-20-04-LTS-005

Y si te encuentras en un sistema con interfaz gráfica, en lugar de redirigir la salida, puedes comenzar incluyendo el comando export DISPLAY=:0, como primera línea de at, para identificar la pantalla donde debe aparecer el resultado.

La ejecución de la tarea

Cuando llegue el momento adecuado (en nuestro ejemplo, las 19:37), veremos que aparece el contenido del directorio actual. Después, se ejecutará el script, que no produce ninguna salida en pantalla y, por último, vuelve a aparecer el contenido del directorio.

Si observas la salida, la segunda vez aparece un archivo más, que es el producido por el script.

También puedes ver que, las copias que hicimos en el artículo anterior con anacrom, tienen como propietario al administrador. Sin embargo, la que acabamos de hacer, es propiedad del usuario.

Resultado de la tarea.

Aplazar-una-tarea-hasta-un-momento-concreto-en-Ubuntu-Server-20-04-LTS-006

Formas de indicar el momento de ejecución

Un aspecto importante para sacar todo el rendimiento posible al comando at es conocer el modo de representar el momento en el que queremos que se ejecute la tarea.

Esta expresión atiende a la forma at [hora] [fecha] y se puede expresar de las siguientes formas:

  • Hora: Indica la hora en la que se llevará a cabo la acción y se puede expresar en cualquiera de los formatos siguientes: HH:MM, HHMM, HH.MM, HH,MM, Hpm, Ham. Donde H ó HH será un valor entero que representa las horas, MM un valor entero que representa los minutos y am ó pm antes del medio día o después del medio día (12:00).

    Además, se pueden utilizar las palabras midnight que se corresponde con las 00:00, noon que representa las 12:00, now que sustituye a la hora actual y teatime que corresponde a las 16:00

  • Fecha: Representa la fecha en la que se ejecutará la acción. Se puede escribir en inglés, utilizando el formato mes día año (por ejemplo, june 17 2013). Incluso podemos suprimir el año cuando nos referimos al actual.

    También podemos utilizar diferentes formatos numéricos: DD.MM.AA, MMDDAA, MM/DD/AA, AA-MM-DD. Donde DD será un valor entero que representa el día, MM un valor entero que representa el mes y AA otro entero que representa el año.

    Además, se pueden utilizar las palabras today, que representa la fecha de hoy, tomorrow que hace referencia a la fecha de mañana y el nombre de los días de la semana (en inglés), que hace referencia a la próxima fecha cuyo día de la semana coincida con el indicado.

  • Otra forma de expresar un momento es con la palabra now seguida de un número y una unidad de tiempo. Por ejemplo, si queremos ejecutar una tarea mañana podríamos escribir now + 1 day.

    Este formato acepta las siguientes unidades de tiempo: min (minutos), minute (minutos), hour (horas), day (días), week (semanas), month (meses) y year (años).

Aquí tienes algunos ejemplos:

at 2pm june 17
at 1013 31.05.14
at teatime tomorrow
at 9:15 today + 5 day
at now + 1 hour
at 08,25 sunday

Otros archivos y comandos relacionados con at

Como ya ocurría con el servicio cron, el administrador dispone de los archivos at.allow y at.deny para determinar qué usuarios pueden programar tareas utilizando at (puedes consultar el artículo Controlar los usuarios que pueden programar tareas en Ubuntu Server 20.04 LTS).

Por otro lado, una forma sencilla de consultar los trabajos que tiene pendientes el servicio atd es utilizando el comando atq:

Se muestra el número de trabajo, la fecha y la hora, la cola y el nombre del usuario al que pertenecen.

Aplazar-una-tarea-hasta-un-momento-concreto-en-Ubuntu-Server-20-04-LTS-007

Como ves en la imagen anterior, solo aparecen los trabajos pendientes de la cuenta de usuario actual. Si queremos mostrar los trabajos de todos los usuarios, necesitaremos ejecutar atq con privilegios administrativos.

Si lo prefieres, en lugar de atq puedes utilizar at con el argumento -l:

at -l

El resultado es completamente equivalente.

Aplazar-una-tarea-hasta-un-momento-concreto-en-Ubuntu-Server-20-04-LTS-008

Y si lo que queremos es comprobar exactamente qué es lo que se va a ejecutar, podemos utilizar el argumento -c, seguido del número de trabajo a examinar, aunque no es objetivo de esta documentación explicar en detalle su contenido:

at -c 2

Vemos que se ha creado un script más complejo al que, al final, se le ha añadido el comando que queremos ejecutar.

Aplazar-una-tarea-hasta-un-momento-concreto-en-Ubuntu-Server-20-04-LTS-009

Por último, también podemos eliminar los trabajos pendientes con el comando atrm. Lógicamente, hay que indicar el número de trabajo que queremos eliminar:

atrm 2

Aquí vemos cómo se ha eliminado el trabajo 2

Aplazar-una-tarea-hasta-un-momento-concreto-en-Ubuntu-Server-20-04-LTS-010

En lugar de atrm, también puedes utilizar el comando at con el argumento -d.

Por cierto, como ocurría con los trabajos pendientes de cron, los de at se guardan en la carpeta /var/spool/at.

Los servicios cron, anacron y atd pueden iniciarse, detenerse, reiniciarse, etc., como cualquier otro servicio del sistema. Si es necesario, puedes consultar los artículos publicados en SomeBooks.es para administrarlos desde la línea de comandos:

O, si prefieres utilizar una interfaz web, te proponemos dos métodos diferentes:

Y esto es todo por el momento. Espero que te haya resultado útil.