Mostrando entradas con la etiqueta cron. Mostrar todas las entradas
Mostrando entradas con la etiqueta cron. Mostrar todas las entradas

Programando tareas en GNU/Linux: cron + crontab

La gente que suele emplear habitualmente Windows conoce a la perfección las "Tareas programadas" y aunque personalmente no conozco a mucha gente que las emplee, sí que cuando menos las conocen. Pues bien, en GNU/Linux existe un planificador de tareas, que también permite ejecutar de forma periódica cosas. Según mi experiencia, incluso más potente que el de Windows, pero como siempre, para gustos...

¿Qué es cron?

cron es el planificador de procesos incluido en prácticamente todos los Unix. Es un pequeño daemon que se encarga de ejecutar los procesos descritos en el fichero crontab cuando corresponda. Por defecto, cron se ejecuta en segundo plano una vez cada minuto y revisa la tabla de tareas que debe de ejecutar (si las hay). Estas tareas se almacenan en /etc/crontab o en /var/spool/cron.
cron permite ejecutar programas como "daemons" sin serlo realmente, ya que es él el que se encarga de realizar la ejecución periódica.

¿Qué es crontab?

crontab es un pequeño fichero de texto, situado en /etc/crontab y que únicamente contiene una pequeña configuración para cada uno de los procesos que se deben de ejecutar. Dicho fichero está distribuido por líneas y cada línea tiene la fecha en la que se debe de repetir (frecuencia de ejecución), el usuario con el que hacerlo (permisos) y el comando a ejecutar.
A mayores del fichero crontab de /etc, que es el general del sistema, cualquier usuario puede tener también su propio fichero crontab. En él puede especificar los comandos que desea y la periodicidad de los mismos. La única diferencia es que no hay campo usuario, ya se se asume que es el propio usuario dueño de dicho fichero. Cualquier usuario puede generar y manejar su propio fichero con el comando crontab.

Tareas en crontab

Una de las partes más esenciales de cron, como ya dijimos es crontab y dentro de éste fichero, lo más lógico es saber cómo crear una nueva línea. Recordemos que cada línea es una tarea o trabajo, así que una nueva línea es un nuevo trabajo que se ejecutará.
Hace ya tiempo escribí una pequeña entrada sobre cron y qué significa cada posición en el fichero. Si te interesa leerla, lo puedes hacer aquí. Lo más importante de aquella entrada era la siguiente imagen,
donde se explica a la perfección cómo crear una línea de ejecución. Algunos ejemplos prácticos:
  • Actualizar sistema a las 3:15 todos los días
    15 3 * * * root apt-get update
    
  • Actualizar sistema todos los domingos a las 10:00
    00 10 * * 0 root apt-get -y update
    
  • Actualizar sistema el día 15 de cada mes a las 15:15
    15 15 15 * * root apt-get update
    
  • Actualizar sistema todos los días de la semana a las 15:15
    15 15 * * 1,2,3,4,5 root apt-get update
    
  • Actualizar sistema el día 1, 15 y 30 de cada mes
    00 00 1,15,30 * * root apt-get update
    
A mayores de poder definir las cadenas como número, cron también contiene cierto literales muy importantes para determinados eventos sumamente reconocidos o empleados. Estos son:
  • @reboot, ejecuta la tarea cuando el sistema se inicia
  • @yearly, ejecuta la tarea sólo una vez al año: 0 0 1 1 *
  • @annually, lo mismo que @yearly
  • @monthly, ejecuta la tarea el primer día del mes: 0 0 1 * *
  • @weekly, ejecuta la tarea el primer minuto de la primera hora de la semana: 0 0 * * 0
  • @daily, diario a las 12:00A.M. 0 0 * * *
  • @midnight, lo mismo que @daily
  • @hourly, ejecuta la tarea el primer minuto de cada hora: 0 * * * *
Y su uso, muy simple,
@reboot  logcheck  /usr/sbin/logcheck -R

La entrada Programando tareas en GNU/Linux: cron + crontab la puede leer en Puppet Linux.
Leer más

Impidiendo la ejecución de varias instancias del mismo proceso

Fijo que muchos de vosotros alguna vez se vio con la necesidad de controlar que un programa que se ejecute automáticamente, por ejemplo desde cron, lo haga sólo si no hay otra instancia del mismo en ejecución. Dicho de otra forma, si ya se lanzó el script y todavía no ha terminado, que no se vuelva a lanzar. Aunque esto parece trivial, impedir que un script se ejecute dos veces puede llegar a ser complicado y nos obliga a tener partes del código similares a éstas,




#!/bin/bash

FILE_SYNC=/var/run/async.lock
if [ -f $FILE_SYNC ]; then
   exit
else
   touch $FILE_SYNC
   ...
   rm -f $FILE_SYNC
fi
Crear un fichero de control de ejecución, es una de las soluciones más habitualmente empleadas, pero este truco es un arma peligrosa ya que si en alguna parte del código termina la ejecución, o se aborta el programa, y el fichero no se borra el script no se volverá a lanzar, ya que para él seguirá un hermano en ejecución.
Para solucionar este tipo de inconvenientes y hacer el código más legible y con menos comprobaciones tenemos la utilidad flockflock es una herramienta que se encarga por nosotros de crear y manejar el fichero de bloqueo de ejecución. Y por ello, si la ejecución de un script está o no activa, bloqueará el fichero de control. Si dicho fichero existe no se permitirá otra ejecución. En caso contrario sí.
Como la mejor forma es verlo con un ejemplo,
5 * * * * root /usr/local/sbin/act.sh
Este es el típico script que se ejecuta desde cron cada 5 minutos, pero nada impide, a nivel del planificador, que haya varias instancias del mismo al mismo tiempo. Si queremos controlar eso, tendrá que ser empleando el truco de añadir código de control. Ahora vamos a lanzar el mismo script, pero controlado.
5 * * * * root /usr/bin/flock -w 0 /tmp/cron.lock /usr/local/sbin/act.sh
En este caso, la primera ejecución creará un fichero, /tmp/cron.lock, que siempre estará presente hasta que termine o alguien la aborte. Cuando finalice, la siguiente ejecución hará lo mismo y nunca habrá dos ejecuciones simultáneas. El código del script será únicamente para hacer el procesado de datos que tenga que hacer, pero no necesitará controlar si hay un hermano ejecutándose.
El contenido del fichero de bloqueo, por cierto, será similar al que sigue,
shell> fuser -v /tmp/cron.lock
             USER   PID  ACCESS COMMAND
cron.lock:   root   7836 f....  flock
             root   7837 f....  php

La entrada Impidiendo la ejecución de varias instancias del mismo proceso la puedes leer en Puppet Linux.
Leer más

Puppet, cron cada 5 minutos

Ya hacía que no hablaba de Puppet en el blog, así que ya tocaba. No se si os acordáis, ya hace bastante tiempo, escribí un post donde explicaba cómo emplear valores aleatorios en puppet, lo que resultaba especialmente útil para un manifiesto que use cron, ya que evitábamos que todas las máquinas tirasen del recurso programado al mismo tiempo.
Pues hoy vamos a ver algo más sobre cron aplicado desde Puppet. Este es el manifiesto de partida,
cron { "update mirror":
   command   => "/usr/local/sbin/update_mirror",
   user      => root,
   hour      => 18,
   minute    => 30,
   subscribe => File["/usr/local/sbin/update_mirror"],
   ensure    => present;
}
Como se puede observar vemos que a las 18:30 se ejecuta el tarea programada. Ahora imaginémonos por un momento que nos interesa que el trabajo se ejecute cada 10 minutos. Pues bien, para hacer eso, podíamos suprimir la línea de la hora y quedarnos con una línea de minutos tal que así,
cron{
   ...
   minute    => [2,15,25,35,45,55],
   ...
}
Realmente esta opción es perfectamente viable, pero el resultado que produce no es muy bonito que digamos, a nivel de cron,
shell> crontab -e
5,15,25,35,45,55 * * * *   /usr/local/sbin/update_mirror
Aunque esta solución es perfectamente válida, quizás no sea la más óptima, ya que si tenemos que ejecutarlo cada minuto, nos quedaría una línea "un poco grande". Así que para optimizarlo, podemos hacer algo tal que así:
cron{
   ...
   minute    => "*/10"
   ...
}
Lo que produciría el siguiente resultado,
shell> crontab -e
*/5 * * * *   /usr/local/sbin/update_mirror
Leer más

Opciones de recycle en Samba

Hace unos días publicaba un artículo sobre cómo activar la papelera de reciclaje en el servicio Samba. Así todos aquellos archivos que se hayan borrados podrán ser recuperados de forma simple sin tener que recurrir al backup por un delete mal pensado.
El primer post realmente fue bastante rápido, la intención era introducir la facility. Ya en este vamos a explicar más en detalle todos los parámetros que existe y se le pueden pasar y lo qué significa cada uno. También tenemos pendiente la creación de un pequeño script que se encargue de purgar los archivos más viejos de la papelera, para evitar que se nos llene. Vamos por partes.
Las opciones:
  • recycle:repository
    path de la carpeta que ejercerá de papelera de reciclaje. Si no es especifica nada, por defecto es .recycle.
  • recycle:directory_mode
    Indica los permisos que tendrá la carpeta de reciclaje cuando se cree por primera vez. El valor por defecto es 0700.
  • recycle:subdir_mode
    Lo mismo que el anterior, pero para los subdirectorios.
  • recycle:keeptree
    Establece si cuando se elimina un archivo dentro de subdirectorios dicho árbol se mantendrá o no.
  • recycle:versions
    Indica si se mantendrán las versiones de los ficheros. Si se eliminan dos ficheros con el mismo nombre y dicha opción no está habilitada sólo permanecerá el último. Si está, se creará una copia con el nombre "Copy #x of filename".
  • recycle:touch
    Especifica si la fecha de modificación de un archivo debe ser actualizada cuando éste se mueve a la papelera.
  • recycle:exclude
    Indica las extensiones de los archivos que serán excluidos de ser enviados a la papelera. Se nombrarán con *.ext y se separarán por |.
  • recycle:excludedir
    Hace exactamente lo mismo, pero con nombres de directorios.
  • recycle:noversions
    Si la opción versions está activa a nivel general, se puede desactivar para una seria de extensiones que se especificarán aquí.
  • recycle:minsize
    Establece el tamaño mínimo de los archivos que serán enviados a la papelera. Si son de menor tamaño se borran directamente.
    El tamaño se indica en bytes.
  • recycle:maxsize
    Establece el tamaño máximo de los archivos que serán enviados a la papelera. Si este tamaño es excedido, se borrarán directamente.
    Con en la opción anterior, el tamaño viene dado en bytes.
Un ejemplo completo de las opciones que se le podrían pasar en la sección global sería,
[global]
   recycle:repository = /srv/Trash
   recycle:versions   = TRUE
   recycle:keeptree   = TRUE
   recycle:touch      = FALSE
   recycle:exclude    = *.tmp | *.o | ~$* | *.~?? | *.log
   recycle:excludedir = /tmp  | /cache
   recycle:noversions = *.dat | *.ini
   recycle:minsize    = 512
   recycle:maxsize    = 51200
Y ahora vamos por la parte que nos falta, que no es otra que borrar aquellos archivos que llevan más de #x días en la papelera, para evitar que ésta aumente de tamaño indefinidamente. Aunque puedes compartir la papelera con los usuarios de Samba/ldap como una carpeta más y que sean ellos quien lo gestionen, quizás la opción de borrar los archivos mayores de 30 días automáticamente no esté demás. Para hacerlo, podemos recurrir a cron y emplear find. Dejando una línea tal que así en nuestro /etc/crontab.
30 2 * * *   root   find /srv/Trash/* -mtime +30 -exec rm {} \;
Todos los días a las 2:30 de la mañana se ejecutará y eliminará aquellos archivos mayores de 30 días, haciendo así que la papelera no aumente de tamaño de forma descontrolada.

La entrada Opciones de recycle en Samba la puedes leer en Puppet Linux.
Leer más

Control de seguridad en crontab

Este pequeño truco realmente puede ser muy útil para sistemas compartidos en el que es necesario dejar como usuario una tarea en cron. Por defecto, dicha tarea si requiere de una contraseña, en crontab se la hay que especificar para que al lanzarse el comando, éste se pueda ejecutar.
Esto por defecto ya llevan un riesgo de seguridad, ya que si alguien lee el fichero, podrá observar la contraseña especificada, escrita en texto plano, tal como se muestra a continuación.
shell> cat /etc/crontab
# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7)
# |  |  |  |  |
# *  *  *  *  * user-name command to be executed
15 0 * * sun root mysql -u root -pYOUR_SECRET_PASSWD -e "CALL ..."
Esto ya de por sí, es un riesgo importante, y la forma de solucionarlo es realmente muy sencilla y se debería de incluir como código de buenas prácticas. Una forma muy sencilla sería esta,
shell> cat /etc/crontab
# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7)
# |  |  |  |  |
# *  *  *  *  * user-name command to be executed
15 0 * * sun root mysql -u root -p`cat $HOME/.my.pass` -e "CALL ..."
En la que la contraseña está escrita en un fichero oculto en la home del usuario que ejecuta el comando y que por defecto sólo tendrá acceso de lectura para él. Es una forma muy simple de proteger la contraseña, pero efectiva para el caso que se propone. Para descubrirla habría que hacer cuando menos una escalada de privilegios en el sistema, lo cual es más complicado que simplemente listar /etc/crontab.

A mayores de esto, algunas aplicaciones UNIX todavía no tiene compilado setproctitle como sistema de llamadas, por lo que si realizamos un ps axu, se podrá ver la línea ejecutada con la contraseña en texto plano. Es muy importante para evitar esto, que las aplicaciones sean compiladas con setproctitle. Actualmente en las principales distribuciones de GNU/Linux cron sí está compilado así, por lo que la contraseña se muestras como XXXXXX.
shell> ps aux
root     80 0.0 0.0 752 20 pts/1 S  13:21 0:00 sh
root     81 0.0 0.0 824 84 pts/1 S+ 13:21 0:00 bash
root     85 0.0 0.0 824 44 pts/1 S+ 13:21 0:00 mysql -u root -pXXXXXX -e...
javier  394 0.0 0.0 820 28 pts/2 Ss 13:54 0:00 bash
javier  402 0.0 0.0 088 80 pts/2 R+ 13:54 0:00 ps aux
...
Leer más

Explicación sencilla de cron

cron es uno de los daemon de GNU/Linux más importantes y habituales en el sistema. Se encarga de lanzar, en segundo plano, tareas programas en fechas concretas y permite por lo tanto realizar tareas repetitivas de forma automática. Dicha definición de tareas está en el fichero /etc/crontab.
Si no estás trabajando diariamente con cron, lo más probable es que la siguiente imagen te pueda ayudar.

A continuación os dejo una pequeña chuleta que la podéis colocar al principio de vuestro crontab y así acordaros siempre del funcionamiento.
# Ejemplo de definición de cron:
# .---------------- minuto (0 - 59) 
# |  .------------- hora (0 - 23) 
# |  |  .---------- dia del mes (1 - 31) 
# |  |  |  .------- mes (1 - 12) O jan,feb,mar,apr ... 
# |  |  |  |  .---- dia de la semana (0 - 6) (Sunday=0 or 7)
# |  |  |  |  |
# *  *  *  *  *   USER  COMMAND
MAILTO="cron@localhost"
SHELL=/bin/sh
...
Leer más

Formulario de contacto

Nombre

Correo electrónico *

Mensaje *

Últimos comentarios