9.7. Tareas programadas
Es muy habitual que las tareas administrativas se vayan repitiendo a lo largo del tiempo con una frecuencia en particular (exportación de datos, copias de seguridad, instalación de actualizaciones, sincronizar el reloj del sistema con un servidor de tiempo, …). Muchas veces, habremos conseguido automatizarlas a través de un script y otras consistirá, símplemente, en ejecutar un determinado programa con unos argumentos específicos. En cualquier caso, para el administrador será de gran ayuda poder iniciar la ejecución de esos programas o scripts de forma automatizada sin tener que estar pendiente de hacerlo a mano en el momento oportuno. Pues bien, en eso consisten las tareas programadas.
En Linux existen dos servicios (cron y anacron) y dos comandos (crontab y at ) que nos facilitan la ejecución de una tarea en un momento concreto. En este apartado vamos a aprender a utilizarlos.
Ejecutar tareas a intervalos regulares
El servicio que se encarga de ejecutar tareas en intervalos regulares es cron, que está formado por el demonio crond y varias tablas que definen los trabajos que se deben ejecutar y con qué frecuencia. Normalmente, crond se inicia durante el arranque del sistema y se activa cada minuto para revisar las tablas y comprobar si debe ejecutar alguna acción.
Tanto el administrador como los propios usuarios gestionan las tablas con los trabajos pendientes mediante el comando crontab.
Para crear la tabla para un trabajo, ejecutaremos el comando crontab con el argumento -e, que indica que queremos editar:
crontab -e
De forma similar a lo que ocurría con el comando edquota en la definición de cuotas, crontab utiliza un editor de textos para que indiquemos nuestras preferencias. Sin embargo, la primera vez que lo ejecutamos, nos da a elegir entre los editores que haya instalados en estos momentos.
Las próximas veces que lo ejecutemos entrará de forma automática en el editor que hayamos elegido. En cualquier caso, si más adelante queremos cambiar de editor, bastará con modificar el valor de las variables de entorno $EDITOR o $VISUAL.
1
Fieles a nuestra costumbre, elegimos nano (aunque tú puedes inclinarte por el editor que prefieras).
Cada entrada en el archivo de crontab tiene seis datos:
- Minuto: Un valor entero entre 0 y 59.
- Hora: Un valor entero entre 0 y 23.
- Día del mes: Un valor entero entre 1 y 31.
- Mes del año: Un valor entero entre 1 y 12.
- Día de la semana: Se puede expresar de dos formas:
- Como un valor entero entre 0 y 7, donde 0 ó 7 = domingo, 1 = lunes, 2 = martes, etc.
- Como un texto con los valores sun, mon, tue, wed, thu, fri y sat.
- Orden que será ejecutada por la Shell. crontab no analiza su contenido, sólo envía a la Shell cualquier cosa que haya después del día de la semana y hasta el final de la línea. Si aparece un carácter de porcentaje (%) será interpretado como el final de la línea por lo que, si necesitamos utilizar este carácter en la orden que le enviemos a la Shell, deberemos ponerle justo delante una barra invertida (\%). Lo que haya antes del primer carácter de porcentaje es enviado a la Shell mientras que todo lo que haya después se envía a la entrada estándar.
Los primeros cinco datos pueden expresarse como valores individuales, como rangos de valores (expresados como dos valores separados por un guión), como una lista de valores individuales o rangos (separados por comas) o con un asterisco (*) que representa todos los valores posibles para ese dato.
También podemos indicar un valor de incremento usando el formato /número. Por ejemplo, si quiero que algo se ejecute entre las 5 y las 15 horas, pero sólo las horas impares, puedo escribir en la segunda columna algo como esto: 5-15/2
Para entender cómo funciona, vamos a crear un pequeño script que haga un duplicado del archivo info.txt, que se encuentra en la carpeta prueba del usuario, añadiéndole la fecha y la hora de la copia. El script puede tener un aspecto como este:
#!/bin/bash cp /home/usuario/prueba/info.txt{,.$(date +%F).$(date +%T)}
A continuación, definiremos una tarea que realice el duplicado a intervalos regulares. Esto lo conseguiremos usando el comando crontab -e para añadir una línea como esta:
0,15,30,45 10-15 * 6 mon-fri /home/usuario/prueba.sh
3
Cuando terminemos de escribirla, salimos del editor pulsando las teclas ctrl + x y asegurándonos de guardar los cambios.
En el ejemplo anterior, el script prueba.sh se ejecutará cada 15 minutos entre las 10 y las 15 horas, de lunes a viernes durante todo el mes de junio.
Observa que también hemos eliminado las líneas de comentario del principio del archivo, para ganar en claridad.
4
Para comprobar que funciona, sólo hay que abrir la carpeta prueba y esperar a que llegue el momento de la siguiente copia.
Llegados a este punto, es importante hacer dos observaciones:
- La tarea programada se ejecutará con los privilegios de la cuenta en la que se ha creado. Es decir, en el ejemplo hemos utilizado la cuenta usuario para crear la tarea programada. Cuando llegue el momento de que el sistema la ejecute, lo hará como si el usuario hubiese escrito la orden en ese preciso momento. La consecuencia es que, si queremos programar tareas administrativas, lo tendremos que hacer con privilegios de superusuario:
sudo crontab -e
- Si el ordenador está apagado cuando se cumple un plazo, la tarea no queda aplazada para cuando el equipo esté disponible. En otras palabras, la tarea correspondiente al plazo que se haya perdido no se recuperará. Para ilustrar esta idea, puedes observar la captura de pantalla anterior. Había una copia programada para las 10:30, pero el equipo estaba apagado en esos momentos y la copia no se ha hecho (aunque sí aparecen la anterior y la posterior, cuando el ordenador estaba funcionando).
Muchos comando que están pensados para usarlos con el servicio cron ofrecerán sus resultados generando sucesos con syslog. Puede resultar conveniente el uso de Logcheck para recibir periódicamente vía e-mail los sucesos que ocasionen estos comandos para tener la certeza de que se están ejecutando según lo planeado (Ver el apartado Registro de sucesos en este mismo capítulo).
Algunos comandos más
Cuando un usuario necesite consultar sus tareas programadas, sólo tendrá que ejecutar el siguiente comando:
crontab -l
Si lo que necesita es eliminar sus tareas programadas de una forma sencilla, bastará con ejecutar el siguiente comando:
crontab -r
En el siguiente ejemplo hemos eliminado las tareas programadas y, a continuación, hemos hecho una consulta.
Gestionar las tareas programadas como superusuario
Podemos utilizar los privilegios de superusuario para asignar tareas programadas a cualquiera de los usuarios del sistema. Para conseguirlo, basta con añadir, al comando crontab, el argumento -u seguido del nombre de la cuenta de cualquier usuario del sistema.
Siguiendo esta pauta, podríamos haber creado la tarea programada para la cuenta usuario usando el siguiente comando:
sudo crontab -u usuario -e
Del mismo modo, podemos consultar las tareas programadas de cualquier usuario del sistema:
sudo crontab -u usuario -l
Incluso podemos eliminar las tareas programadas que hayamos creado previamente para un usuario particular o que haya creado él mismo.
sudo crontab -u usuario -r
Controlar los usuarios que pueden programar tareas
Puede que los archivos cron.allow y cron.deny no existan de forma predeterminada en la carpeta /etc, pero pueden crearse usando cualquier editor de textos.
En Ubuntu, de forma predeterminada, todos los usuarios pueden crear tareas programadas. Sin embargo, el administrador tiene la posibilidad de quitarle esa facultad a cualquier usuario del sistema. Para lograr ese propósito, pueden utilizarse dos archivos diferentes, llamados cron.allow y cron.deny, que se encuentran dentro del directorio /etc.
La idea general es utilizar el archivo cron.deny para permitir la creación de tareas programadas a todos los usuarios, salvo un número reducido, que relacionamos dentro de este archivo.
La otra opción es impedir la creación de tareas programadas a todos los usuarios, salvo a un número reducido, que relacionaremos dentro del archivo cron.allow.
Para comprobarlo, usaremos privilegios de superusuario para crear el archivo /etc/cron.deny e incluiremos el nombre de un usuario. Para lograrlo, podemos usar, como siempre, el editor nano.
sudo nano /etc/cron.deny
1
Cuando terminemos, salimos del editor pulsando las teclas ctrl + x y asegurándonos de guardar los cambios.
Cuando tratemos de crear una tarea programada desde la cuenta usuario, obtendremos un error como el de la imagen siguiente…
2
Se producirá el error incluso cuando tratemos de crear la tarea programada para el usuario usando privilegios de root.
También podemos probar a la inversa: Si lo hacemos al contrario e incluimos el nombre de la cuenta usuario dentro del archivo cron.allow, comprobaremos que ahora no se podrán programar tareas para ningún otro usuario.
3
Editamos el archivo cron.allow con privilegios de superusuario e incluimos el nombre de la cuenta usuario.
Por último, aclarar dos detalles:
- Cuando necesitamos incluir varios nombres de cuentas en los archivos cron.allow o cron.deny, deberemos escribir cada nombre de cuenta en una línea distinta del archivo.
- En lugar de una cuenta de usuario, podemos utilizar la palabra ALL para representarlas a todas.
¿Dónde se guardan las tareas programadas?
Las tareas que se crean con el comando crontab se guardan en el directorio /var/spool/cron/crontabs con el nombre del usuario al que pertenecen.
Cuando eliminemos las tareas de un usuario (por ejemplo con sudo crontab -u usuario -r) desaparecerá su archivo correspondiente en el directorio /var/spool/cron/crontabs.
Además de los archivos anteriores, dentro del directorio /etc encontramos el archivo crontab y los directorios cron.d, cron.hourly, cron.daily, cron.monthly y cron.weekly, todos ellos relacionados con el servicio cron.
El archivo /etc/crontab contiene una serie de tareas programadas de forma genérica para el sistema.
La idea es que se ejecuten de forma sistemática las cuatro tareas programadas que hay definidas en la parte inferior del archivo. En realidad, todas ellas son prácticamente iguales y consisten en ejecutar uno a uno, todos los scripts que contengan los directorios cron.hourly, cron.daily, cron.monthly y cron.weekly.
Lógicamente, lo que cambia es la definición del periodo:
- En la primera (17 * * * *), los scripts que se encuentren dentro del directorio cron.hourly se ejecutarán en el minuto 17 de cada hora, todos los días.
- En la segunda (25 6 * * *), los scripts que se encuentren dentro del directorio cron.daily se ejecutarán a las 6:25 de la mañana, también todos los días.
- En la tercera (47 6 * * 7), los scripts que se encuentren dentro del directorio cron.weekly se ejecutarán todos los domingos a las 6:47.
- En la cuarta (52 6 1 * *), los scripts que se encuentren dentro del directorio cron.monthly se ejecutarán el día 1 de cada mes a las 6:52 .
Por último, el directorio cron.d se utiliza en otras distribuciones para guardar los archivos cron.allow y cron.deny, que, como ya hemos dicho, en Ubuntu se encuentran dentro del directorio /etc.
Ejecución de tareas asíncronas
El servicio cron resulta muy útil cuando tratamos con servidores u otros equipos pensados para funcionar continuamente. Sin embargo, en los equipos que pueden permanecer apagados durante periodos indeterminados, como ordenadores de escritorio o portátiles, cron puede resultar inútil, porque en el momento en el que se venza un plazo, el ordenador puede estar desconectado y, como ya vimos antes, la tarea correspondiente no se recuperará.
En estos casos, puede resultar muy útil el servicio anacron (el nombre proviene del inglés anachronistic cron). A diferencia de cron, si programamos una tarea para una hora en particular y, en ese momento, el ordenador está apagado, la tarea se retomarán en cuanto sea posible. Esto nos permitirá atender tareas críticas que no puedan dejar de atenderse.
Pueden atenderse las tareas asignadas a cron con un periodo diario (daily), semanal (weekly) o mensual (monthly). Sin embargo, anacron no atiende trabajos que cron deba atender cada hora (hourly).
Como veremos más abajo, anacron mantiene archivos con marcas de tiempo en la carpeta /var/spool/anacron para saber en qué momento se ejecutan las tareas.
Cuando se ejecuta anacron, lee la lista de tareas pendientes, que se encuentran definidas en el archivo /etc/anacrontab y comprueba si ha pasado el número adecuado de días desde la última vez que se ejecutó la tarea. Si es necesario, se ejecuta.
A diferencia de cron, anacron es ejecutado por los scripts de inicio del sistema o por alguna tarea programada y, cuando acaba su trabajo, deja de ejecutarse.
Por cada tarea programada en este archivo se incluyen los siguientes valores:
- Un número de días. También puede especificarse como @monthly para indicar que la tarea sólo se ejecute una vez al mes, independientemente del número de días que tenga.
- Un retraso en minutos. Indica el número de minutos que debe esperar el sistema para ejecutar la tarea después de ejecutar anacron. Su objetivo es evitar una avalancha de tareas ejecutándose a la vez cuando arrancamos el sistema.
- El nombre de la tarea. Puede ser cualquier conjunto de caracteres, excepto la barra (/), pero debe ser único, porque será el nombre que utilice anacron para crear el archivo en /var/spool/anacron, donde guarda la fecha de la última vez que la ha ejecutado.
- La tarea a realizar.
Para incluir modificaciones en el archivo /etc/anacrontab sólo necesitamos un editor de textos:
sudo nano /etc/anacrontab
Ejecutar tareas en un momento concreto
En ocasiones, en lugar de realizar una tarea de forma periódica, lo que necesitamos es ejecutarla sólo una vez, pero en un momento particular del futuro. Para cumplir con ese objetivo, disponemos del comando 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 comando at guarda los valores de las variables de entorno y el directorio actual y los utilizará para ejecutar la tarea, de forma que no le afecten los cambios que se produzcan después de programarla.
Por ejemplo, si quiero que se ejecute el editor de textos, de forma automática, a las 21:27, sólo tendría que escribir en la consola una orden como esta:
at 21:27
Como vamos a ejecutar programas que utilizan la interfaz gráfica, usamos el comando export DISPLAY=:0 para identificar la pantalla donde deben aparecer.
Veremos que aparece un prompt específico de at donde escribimos los comandos que queramos que se ejecuten. Cuando escribamos el nombre de más de un comando o programa, como en este ejemplo, debemos saber que no se iniciará la ejecución del segundo 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 varias tareas que puedan iniciar su ejecución de forma simultánea sólo tendremos que ejecutar at varias veces.
1
Cuando hayamos terminado de escribir, pulsamos la combinación de teclas Ctrl + D. En la pantalla aparecerá la marca <EOT>.
La expresión del momento en el que se producirá la ejecució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).
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
En otro orden de cosas, 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.
Una forma sencilla de consultar los trabajos que tiene pendientes el servicio atd es utilizando el comando atq:
2
Se muestra el número de trabajo, la fecha y la hora, la cola y el nombre del usuario al que pertenecen.
El comando atq muestra los trabajos pendientes del usuario, salvo que lo ejecutemos como superusuario. En este caso, se muestran los trabajos de todos los usuarios.
Si lo prefieres, en lugar de atq puedes utilizar at con el argumento -l:
at -l
Si lo que queremos es comprobar exactamente qué es lo que se va a ejecutar, podemos utilizar el argumento -c, aunque no es objetivo de esta documentación explicar en detalle su contenido:
at -c 7
3
Vemos que se ha creado un script más complejo al que, al final, se le ha añadido el comando que queremos ejecutar.
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
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 el apartado Gestión de servicios, en este mismo capítulo.
Administrar tareas programadas desde la interfaz gráfica
Una vez que sabemos cómo funciona la programación de tareas en Linux, ha llegado la hora de conocer una herramienta de la Interfaz gráfica de Gnome que puede facilitarnos mucho la labor. Me refiero a la herramienta Tareas programadas, aunque, en realidad, el programa se llama gnome-schedule.
Esta herramienta no se encuentra instalada en Ubuntu de forma predeterminada, pero sí se incluye en sus repositorios, por lo que podemos instalarla utilizando el Centro de software de Ubuntu o, sencillamente, abriendo una ventana de terminal y escribiendo la siguiente orden:
sudo apt-get install gnome-schedule
Para ejecutarlo, recurrimos al Dash…
1
Sólo tenemos que comenzar a escribir el nombre de la herramienta y hacer clic sobre su icono cuando aparezca.
En la ventana principal de la aplicación veremos las tareas programadas que se encuentran pendientes de su ejecución. También encontraremos diferentes herramientas para crear tareas nuevas y modificar o borrar las existentes.
Desde Tareas programadas podremos crear tareas que se ejecuten a intervalos regulares o que se ejecuten una sola vez.
La forma más sencilla de crear una nueva tarea programada es hacer clic en el botón Nuevo.
En la ventana podremos elegir entre tres opciones:
- Crear una tarea que se lanzará repetidamente, a intervalos regulares. En definitiva, supone utilizar una interfaz gráfica para cron.
- Crear una tarea que se lanza una sola vez, que actúa como una interfaz gráfica para at.
- Crear una tarea desde una plantilla predefinida. Esto nos permite tener plantillas de tareas programables, de forma que, si tuviese una tarea que ejecuto de vez en cuando, pero sin coincidir con intervalos regulares, puedo crear una plantilla con las características de la tarea y programarla cuando sea necesario. De esta forma se evita tener que volver a reconstruirla cada vez.
Crear una nueva tarea programada
Este es el propósito principal de este programa. Para lograrlo, bastará con hacer clic en el botón Una tarea que se lanzará repetidamente de la ventana anterior.
Cuando aparezca la ventana Crear una tarea programada nueva, sólo hay que rellenar sus datos y terminar haciendo clic sobre el botón Añadir.
1
También podemos hacer clic sobre Añadir como plantilla si en lugar de crear la tarea queremos usarla como modelo para otras tareas futuras.
En la parte superior de la ventana incluiremos una breve descripción, debajo el nombre del programa, del comando o del script que queramos ejecutar y el comportamiento que debe tener el sistema con la tarea programada (aplicar el comportamiento predeterminado, suprimir su salida, tratarlo como una aplicación gráfica o suprimir la salida gráfica).
2
En este ejemplo, ejecutaremos de forma automática el editor de textos, que es una aplicación gráfica.
Más abajo, disponemos de dos formas de expresar la frecuencia con la que debe ejecutarse la tarea:
- Si elegimos Básico, podremos elegir los periodos de forma genérica: Cada minuto, cada hora, cada día, cada mes, cada semana o al reiniciar.
- Si elegimos Avanzado, podremos expresar los períodos del mismo modo que lo hacíamos en crontab.
Si hacemos clic sobre el botón Editar, aparecerá una nueva ventana que nos ayuda a introducir los periodos de tiempo
Cuando hagamos clic sobre el botón Aceptar, seguiremos con la definición del periodo…
4
Así, podremos indicar, por ejemplo, que el programa se ejecute todos los días entre julio y septiembre.
En la parte inferior de la ventana se incluye una explicación textual de la frecuencia que hayamos establecido.
Como hemos dicho al principio, para terminar, deberemos pulsar el botón Añadir o Añadir como plantilla.
Al salir, recibiremos un aviso que nos informa de que la tarea programada se ejecutará desde el directorio personal del usuario que la ha creado.
6
Cuando volvamos a la ventana principal de gnome-schedule comprobaremos que la nueva tarea aparece en la lista.
Crear una tarea que se ejecute en un momento concreto
También podemos utilizar gnome-schedule como alternativa al comando at para ejecutar una tarea en particular una sola vez en un momento concreto del futuro.
Para crear una tarea de este tipo, hacemos clic sobre el botón Nuevo de la ventana principal.
1
A continuación, hacemos clic sobre el botón sobre el botón Una tarea que se lanza una sola vez de la ventana Añadir una tarea programada.
Aparecerá una ventana titulada Crear una tarea programada nueva. En ella, incluiremos un título para la tarea y una fecha y una hora en la que debe ejecutarse.
A continuación, elegiremos la tarea que queremos programar. En este ejemplo, haremos que el ordenador se apague automáticamente cuando llegue el momento indicado. Para lograrlo, escribimos algo como esto:
sudo shutdown -h now
Al salir, recibiremos un aviso que nos informa de que la tarea programada se ejecutará desde el directorio en el que se está ejecutando el planificador de tareas que, normalmente, será el directorio personal del usuario que la ha creado.
De vuelta en la ventana principal, podremos comprobar que ya aparece la nueva tarea en la lista de tareas programadas.
Modificar o eliminar tareas programadas desde gnome-schedule
En cualquier momento, podremos volver a ejecutar gnome-schedule para realizar cambios en la programación de tareas que tengamos definidas previamente. Incluso podremos editar (modificar) o eliminar aquellas tareas que hayamos definido desde la línea de comandos. Tampoco importa si las tareas son periódicas o para ejecutarlas en un momento determinado.
Para lograrlo, basta con hacer doble clic sobre la tarea en la que queramos hacer los cambios. También podemos seleccionarla haciendo clic sobre ella y, a continuación, pulsando la tecla Intro.
1
Incluso podemos seleccionar la tarea (haciendo clic sobre ella) y, a continuación, hacer clic sobre el botón Editar.
Al hacerlo, aparecerá la ventana Editar una tarea programada con los datos de la tarea que hayamos elegido.
Del mismo modo, podemos borrar (eliminar) cualquiera de las tareas programadas. Sólo tendremos que seleccionarla haciendo clic sobre ella y, a continuación, pulsando la tecla Supr.
1
También podemos seleccionar la tarea (haciendo clic sobre ella) y, después, hacer clic sobre el botón Eliminar.
En cualquier caso, aparecerá un aviso con el objeto de evitar que borremos tareas por error.