GNU/Linux >> Tutoriales Linux >  >> Linux

¿Por qué mi crontab no funciona y cómo puedo solucionarlo?

Solución 1:

Cómo solucionar todos los problemas/problemas relacionados con crontab (Linux)

Esta es una wiki de la comunidad, si nota algo incorrecto con esta respuesta o si tiene información adicional, edítela.

Primero, terminología básica:

  • cron(8) es el demonio que ejecuta los comandos programados.
  • crontab(1) es el programa utilizado para modificar los archivos crontab(5) del usuario.
  • crontab(5) es un archivo por usuario que contiene instrucciones para cron(8).

A continuación, información sobre cron:

Cada usuario de un sistema puede tener su propio archivo crontab. La ubicación de los archivos raíz y crontab del usuario dependen del sistema, pero generalmente están por debajo de /var/spool/cron .

Hay un /etc/crontab en todo el sistema archivo, el /etc/cron.d El directorio puede contener fragmentos de crontab que también son leídos y accionados por cron. Algunas distribuciones de Linux (p. ej., Red Hat) también tienen /etc/cron.{hourly,daily,weekly,monthly} que son directorios, scripts dentro de los cuales se ejecutarán cada hora/día/semana/mes, con privilegio de root.

root siempre puede usar el comando crontab; los usuarios regulares pueden o no tener acceso. Cuando editas el archivo crontab con el comando crontab -e y guárdelo, crond verifica su validez básica pero no garantiza que su archivo crontab esté formado correctamente. Hay un archivo llamado cron.deny que especificará qué usuarios no pueden usar cron. El cron.deny la ubicación del archivo depende del sistema y se puede eliminar, lo que permitirá a todos los usuarios usar cron.

Si la computadora no está encendida o el demonio crond no se está ejecutando, y la fecha/hora para ejecutar un comando ha pasado, crond no se pondrá al día ni ejecutará consultas anteriores.

detalles de crontab, cómo formular un comando:

Un comando crontab está representado por una sola línea. No puedes usar \ para extender un comando a varias líneas. El hash (# ) representa un comentario que significa que cron ignora cualquier cosa en esa línea. Los espacios en blanco iniciales y las líneas en blanco se ignoran.

Tenga MUCHO cuidado al usar el porcentaje (% ) inicie sesión en su comando. A menos que se escapen \% se convierten en saltos de línea y todo lo que sigue al primer % sin escape se pasa a su comando en stdin.

Hay dos formatos para los archivos crontab:

  • Crontabs de usuario

     # 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)
     # |  |  |  |  |
     # *  *  *  *  *   command to be executed
    
  • Todo el sistema /etc/crontab y /etc/cron.d fragmentos

     # 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
    

Tenga en cuenta que este último requiere un nombre de usuario. El comando se ejecutará como el usuario designado.

Los primeros 5 campos de la línea representan la(s) hora(s) en que se debe ejecutar el comando. Puede usar números o, cuando corresponda, nombres de días/meses en la especificación de la hora.

  • Los campos están separados por espacios o tabulaciones.
  • Una coma (, ) se usa para especificar una lista, por ejemplo, 1,4,6,8, lo que significa que se ejecuta en 1,4,6,8.
  • Los rangos se especifican con un guión (- ) y puede combinarse con listas, p. 1-3,9-12 lo que significa entre 1 y 3 y luego entre 9 y 12.
  • El / El carácter se puede utilizar para introducir un paso, p. 2/5 lo que significa comenzar en 2 y luego cada 5 (2,7,12,17,22...). No se envuelven más allá del final.
  • Un asterisco (* ) en un campo significa el rango completo para ese campo (por ejemplo, 0-59 para el campo de minutos).
  • Los rangos y los pasos se pueden combinar, p. */2 significa comenzar en el mínimo para el campo relevante y luego cada 2, p. 0 para minutos (0,2...58), 1 para meses (1,3... 11) etc.

Depuración de comandos cron

¡Revisa el correo!

De forma predeterminada, cron enviará por correo cualquier resultado del comando al usuario con el que está ejecutando el comando. Si no hay salida no habrá correo. Si desea que cron envíe correo a una cuenta diferente, puede configurar la variable de entorno MAILTO en el archivo crontab, por ejemplo,

[email protected]
1 2 * * * /path/to/your/command

Capture la salida usted mismo

Puede redirigir stdout y stderr a un archivo. La sintaxis exacta para capturar la salida puede variar según el shell que esté usando el cron. Aquí hay dos ejemplos que guardan todos los resultados en un archivo en /tmp/mycommand.log :

1 2 * * * /path/to/your/command &>/tmp/mycommand.log
1 2 * * * /path/to/your/command >/tmp/mycommand.log 2>&1

Mira los registros

Cron registra sus acciones a través de syslog, que (dependiendo de su configuración) a menudo van a /var/log/cron o /var/log/syslog .

Si es necesario, puede filtrar las declaraciones cron con, por ejemplo,

grep CRON /var/log/syslog 

Ahora que hemos repasado los conceptos básicos de cron, dónde están los archivos y cómo usarlos, veamos algunos problemas comunes.

Compruebe que cron se está ejecutando

Si cron no se está ejecutando, sus comandos no se programarán...

ps -ef | grep cron | grep -v grep

debería obtener algo como

root    1224   1  0 Nov16 ?    00:00:03 cron

o

root    2018   1  0 Nov14 ?    00:00:06 crond

Si no, reinícialo

/sbin/service cron start

o

/sbin/service crond start

Puede haber otros métodos; usa lo que proporciona tu distribución.

cron ejecuta su comando en un entorno restringido.

Es probable que las variables de entorno disponibles sean muy limitadas. Por lo general, solo obtendrá unas pocas variables definidas, como $LOGNAME , $HOME y $PATH .

De particular interés es el PATH está restringido a /bin:/usr/bin . La gran mayoría de los problemas de "mi secuencia de comandos cron no funciona" se deben a esta ruta restrictiva . Si su comando está en una ubicación diferente, puede resolver esto de varias maneras:

  1. Proporcione la ruta completa a su comando.

     1 2 * * * /path/to/your/command
    
  2. Proporcione una RUTA adecuada en el archivo crontab

     PATH=/bin:/usr/bin:/path/to/something/else
     1 2 * * * command 
    

Si su comando requiere otras variables de entorno, también puede definirlas en el archivo crontab.

cron ejecuta tu comando con cwd ==$HOME

Independientemente de dónde resida el programa que ejecute en el sistema de archivos, el directorio de trabajo actual del programa cuando cron lo ejecute será el directorio de inicio del usuario . Si accede a archivos en su programa, deberá tener esto en cuenta si usa rutas relativas o (preferiblemente) solo usa rutas calificadas en todas partes, y evitará a todos una gran confusión.

El último comando en mi crontab no se ejecuta

Cron generalmente requiere que los comandos terminen con una nueva línea. Edite su crontab; vaya al final de la línea que contiene el último comando e inserte una nueva línea (presione enter).

Comprueba el formato crontab

No puede usar un crontab con formato crontab de usuario para /etc/crontab o los fragmentos en /etc/cron.d y viceversa. Un crontab con formato de usuario no incluye un nombre de usuario en la sexta posición de una fila, mientras que un crontab con formato de sistema incluye el nombre de usuario y ejecuta el comando como ese usuario.

Puse un archivo en /etc/cron.{por hora,diario,semanal,mensual} y no se ejecuta

  • Compruebe que el nombre del archivo no tenga una extensión; consulte las partes ejecutadas
  • Asegúrese de que el archivo tenga permisos de ejecución.
  • Dígale al sistema qué usar al ejecutar su secuencia de comandos (p. ej., ponga #!/bin/sh en la parte superior)

Errores relacionados con la fecha de Cron

Si su fecha ha sido modificada recientemente por un usuario o una actualización del sistema, zona horaria u otro, entonces crontab comenzará a comportarse de manera errática y exhibirá errores extraños, a veces funcionando, a veces no. Este es el intento de crontab de tratar de "hacer lo que quieras" cuando el tiempo cambia debajo de él. El campo "minuto" dejará de tener efecto después de cambiar la hora. En este escenario, solo se aceptarían asteriscos. Reinicie cron y vuelva a intentarlo sin conectarse a Internet (para que la fecha no tenga la posibilidad de restablecerse en uno de los servidores de hora).

Signos de porcentaje, otra vez

Para enfatizar el consejo sobre los signos de porcentaje, aquí hay un ejemplo de lo que cron hace con ellos:

# cron entry
* * * * * cat >$HOME/cron.out%foo%bar%baz

creará el archivo ~/cron.out que contiene las 3 líneas

foo
bar
baz

Esto es particularmente intrusivo cuando se usa el date dominio. Asegúrese de escapar de los signos de porcentaje

* * * * * /path/to/command --day "$(date "+\%Y\%m\%d")"

Cuidado con Sudo

cuando se ejecuta como usuario no root,

crontab -e

abrirá el crontab del usuario, mientras

sudo crontab -e

abrirá el crontab del usuario root. No se recomienda ejecutar comandos sudo en un trabajo cron, por lo que si intenta ejecutar un comando sudo en el cron de un usuario, intente mover ese comando al cron de root y elimine sudo del comando.

Solución 2:

Debian Linux y su derivado (Ubuntu, Mint, etc.) tienen algunas peculiaridades que pueden impedir que se ejecuten sus trabajos cron; en particular, los archivos en /etc/cron.d , /etc/cron.{hourly,daily,weekly,monthly} debe :

  • ser propiedad de root
  • solo se puede escribir por root
  • no se puede escribir por grupo u otros usuarios
  • tener un nombre sin puntos '.' o cualquier otro carácter especial excepto '-' y '_' .

El último perjudica regularmente a los usuarios desprevenidos; en particular, cualquier script en una de estas carpetas llamada whatever.sh , mycron.py , testfile.pl , etc. no ser ejecutado, jamás.

En mi experiencia, este punto en particular ha sido, con mucho, la razón más frecuente de un cronjob que no se ejecuta en Debian y derivados.

Ver man cron para más detalles, si es necesario.

Solución 3:

Si sus cronjobs dejan de funcionar, verifique que su contraseña no haya caducado, ya que una vez que lo ha hecho, todos los cronjobs se detienen.
Habrá mensajes en /var/log/messages similar al siguiente que muestra problemas con la autenticación del usuario:

(username) FAILED to authorize user with PAM (Authentication token is no longer valid; new one required)

Solución 4:

Horarios poco comunes e irregulares

Cron se considera un programador muy básico y la sintaxis no permite que un administrador formule programaciones poco comunes.

Considere el siguiente trabajo que comúnmente se explicaría para "ejecutar command cada 5 minutos" :

*/5 * * * * /path/to/your/command

contra:

*/7 * * * * /path/to/your/command

que no siempre ejecutar command cada 7 minutos .

Recuerde que el / El carácter se puede usar para introducir un paso, pero esos pasos no terminan más allá del final de una serie, p. */7 que coincide cada 7 minutos a partir de los minutos 0-59 es decir, 0,7,14,21,28,35,42,49,56 pero entre una hora y la siguiente habrá solo 4 minutos entre lotes , después de 00:56 una nueva serie comienza en 01:00 , 01:07 etc. (y los lotes no se ejecutarán en 01:03 , 01:10 , 01:17 etc.).

¿Qué hacer en su lugar?

Crea varios lotes

En lugar de un solo trabajo cron, cree varios lotes que combinados den como resultado el programa deseado.

Por ejemplo, para ejecutar un lote cada 40 minutos (00:00, 00:40, 01:20, 02:00, etc.), cree dos lotes, uno que se ejecute dos veces en las horas pares y otro que se ejecute solo en las horas impares:

# The following lines create a batch that runs every 40 minutes i.e.

# runs on   0:00, 0:40,        02:00, 02:40         04:00 etc to 22:40
0,40 */2 * * * /path/to/your/command

# runs on               01:20,               03:20,       etc to 23:20
20 1/2 * * * /path/to/your/command

# Combined: 0:00, 0:40, 01:20, 02:00, 02:40, 03:20, 04:00 etc.

Ejecute sus lotes con menos frecuencia

En lugar de ejecutar su lote cada 7 minutos, que es un programa difícil de desglosar en varios lotes, simplemente ejecútelo cada 10 minutos.

Comience sus lotes con más frecuencia (pero evita que se ejecuten varios lotes al mismo tiempo)

Muchos programas extraños evolucionan porque los tiempos de ejecución de los lotes aumentan/fluctúan y luego los lotes se programan con un poco de margen de seguridad adicional para evitar que las ejecuciones posteriores del mismo lote se superpongan y se ejecuten simultáneamente.

En cambio, piense de manera diferente y cree un cronjob que fallará correctamente cuando una ejecución anterior aún no haya terminado, pero que se ejecutará de otra manera. Vea estas preguntas y respuestas:

* * * * * /usr/bin/flock -n /tmp/fcj.lockfile /usr/local/bin/frequent_cron_job 

Eso iniciará casi inmediatamente una nueva ejecución una vez que se haya completado la ejecución anterior de /usr/local/bin/frequent_cron_job.

Comience sus lotes con más frecuencia (pero salga con gracia cuando las condiciones no sean las adecuadas)

Dado que la sintaxis cron es limitada, puede decidir colocar condiciones y lógica más complejas en el propio trabajo por lotes (o en un script contenedor alrededor del trabajo por lotes existente). Eso le permite utilizar las capacidades avanzadas de sus lenguajes de secuencias de comandos favoritos, para comentar su código y evitará construcciones difíciles de leer en la propia entrada crontab.

En bash el seven-minute-job entonces se vería algo así como:

#!/bin/bash
# seven-minute-job
# This batch will only run when 420 seconds (7 min) have passed
# since the file /tmp/lastrun was either created or updated

if [ ! -f /tmp/lastrun ] ; then
    touch /tmp/lastrun
fi

if [ $(( $(date +%s) - $(date -r /tmp/lastrun +%s) )) -lt 420 ] ; then
     # The minimum interval of 7 minutes between successive batches hasn't passed yet.
    exit 0
fi

####  Start running your actual batch job below
  
/path/to/your/command

#### actual batch job is done, now update the time stamp
date > /tmp/lastrun
#EOF

Que luego puede (intentar) ejecutar con seguridad cada minuto:

* * * * * /path/to/your/seven-minute-job

Un problema diferente, pero similar, sería programar un lote para que se ejecute el primer lunes de cada mes (o el segundo miércoles), etc. Simplemente programe el lote para que se ejecute todos los lunes y salga cuando la fecha no esté entre el 1 o el 7 y el día. de la semana no es lunes.

#!/bin/bash
# first-monday-of-the-month-housekeeping-job

# exit if today is not a Monday (and prevent locale issues by using the day number) 
if [ $(date +%u) != 1 ] ; then
  exit 0
fi

# exit if today is not the first Monday
if [ $(date +%d) -gt 7 ] ; then
  exit 0
fi

####  Start running your actual batch job below
  
/path/to/your/command

#EOF

Que luego puede (intentar) ejecutar con seguridad todos los lunes:

0 0 * * 1 /path/to/your/first-monday-of-the-month-housekeeping-job

No utilices cron

Si sus necesidades son complejas, puede considerar usar un producto más avanzado que esté diseñado para ejecutar programaciones complejas (distribuidas en varios servidores) y que admita disparadores, dependencias de trabajo, manejo de errores, reintentos y monitoreo de reintentos, etc. La jerga de la industria sería "empresa " programación de trabajos y/o "automatización de la carga de trabajo".

Solución 5:

Específico de PHP

Si tiene algún trabajo cron como:

php /bla/bla/something.php >> /var/logs/somelog-for-stdout.log

Y en caso de errores, espere que se los envíen, pero no lo hacen, verifique esto.

PHP por defecto no envía errores a STDOUT. @ver https://bugs.php.net/bug.php?id=22839

Para solucionar esto, agregue cli`s php.ini o en su línea (o en su contenedor bash para PHP) estos:

  • --define display_startup_errors=1
  • --define display_errors='stderr'

La primera configuración le permitirá tener fatales como 'Memory oops' y la segunda, para redirigirlos a STDERR. Solo después de que pueda dormir bien, ya que todo se enviará a su correo raíz en lugar de solo iniciar sesión.


Linux
  1. Por qué los datos son importantes y cómo protegerlos

  2. ¿Por qué no puedo dividir un archivo .ape?

  3. ¿Cómo puede el trabajo remoto y la planificación de la continuidad del negocio mitigar el impacto del COVID-19 (Coronavirus)?

  4. ¿Cómo puedo ordenar ls por propietario y grupo?

  5. ¿Por qué no funciona sftp rmdir?

Cómo encontrar si un paquete está instalado o no en Linux y Unix

Cómo y por qué usar Linux para instalar Telnet

¿Cómo puedo comprobar que existe un archivo y ejecutar un comando si no es así?

¿Cómo puedo hacer que la sesión de sudo sea de una hora y no de unos minutos en Ubuntu 10.04?

¿Cómo puedo hacer que 'diff -X' ignore rutas específicas y no nombres de archivos?

¿Cómo puedo montar una partición en cada reinicio?