Cómo configurar un trabajo cron de raíz correctamente

36

Traté de configurar un trabajo cron de root para ejecutar un script Bash como root, para ejecutar en el minuto 7,37, cada hora, todos los días del mes, todos los meses. Este script está ubicado /usr/biny nombrado tunlrupdate.sh. Actualiza el DNS de Tunlr.

$ ls -l /usr/bin/tunlrupdate.sh 
-rwxr-xr-x 1 root root 2133 Sep 24 15:42 /usr/bin/tunlrupdate.sh

Este script de Bash está disponible aquí .

Cuando se invoca, el script escribe lo que sucede en un registro ubicado en /var/log/tunlr.log

Para agregar este trabajo cron de root usé el estándar para crontab de root

sudo crontab -e

E insertó estas 2 líneas al final. Espero que cron ejecute el script como root.

# check for updated Tunlr DNS every 30 minutes at the hour + 7 mn and hour + 37 mn
07,37 * * * * root /usr/bin/tunlrupdate.sh

Un comando posterior sudo crontab -lconfirmó que el trabajo cron ha sido insertado.

Reinicié Ubuntu y estaba revisando el archivo de registro si el trabajo cron se inició correctamente. Sin embargo, no hay nada en el archivo de registro que /var/log/tunlr.logsignifique que el trabajo nunca se inició con éxito.

Verifiqué que si ejecuto el script desde la línea de comando

sudo /usr/bin/tunlrupdate.sh

entonces el archivo de registro se actualiza en consecuencia.

¿Por qué este trabajo cron no se ejecuta según lo planeado en mi sistema?

ACTUALIZACIÓN 1: Todas las soluciones propuestas hasta ahora no funcionan. Agradezco a Olli por una CLI para enumerar el registro del sistema sudo grep CRON /var/log/syslog. Sin embargo, recibí un error CRON

CRON[13092]: (root) CMD (  [ -x /usr/lib/php5/maxlifetime ] && [ -d /var/lib/php5 ]
&& find /var/lib/php5/ -depth -mindepth 1 -maxdepth 1 -type f -cmin +$(/usr/lib/php
/maxlifetime) ! -execdir fuser -s {} 2>/dev/null \; -delete)

con la RUTA sugerida = inserción y uso de ruta absoluta desde la raíz para funciones en el script o sin las soluciones sugeridas aquí. Todavía recibo este error.

Después de algunas búsquedas, identifiqué el error en el archivo /usr/lib/php5/maxlifetimecomo se explica aquí :Change #!/bin/sh -e --> #!/bin/sh -x

Luego enumerando el registro de errores CRON en mi sistema

sudo grep CRON /var/log/syslog
Feb 11 18:07:01 Marius-PC CRON[14067]: (root) CMD (root /usr/bin/tunlrupdate.sh)
Feb 11 18:07:01 Marius-PC CRON[14066]: (root) MAIL (mailed 1 byte of output; but got
status 0x00ff, #012)

Todavía no consigo ejecutar el script bash. Esta vez no se muestra ningún error en el registro. Para asegurarme de que este no era el contenido del guión, reduje el guión a las siguientes 3 líneas:

#!/bin/bash
LOGFILE=/var/log/tunlr.log
echo $LOGFILE >> $LOGFILE

Todavía no consigo el trabajo cron. Nada está escrito en el archivo de registro. Entonces, ¿puede ser que un script vacío no se ejecute en cron? No lo entiendo Sé probar un script reducido a estas 2 líneas:

#!/bin/bash
exit 0

Y sigue siendo el mismo registro de errores. El script cron no pasa por ...

Antonio
fuente
Si desea que sea un trabajo temporal "root", debe ser root y escribir crontab -e. También solo tiene que iniciar sesión como root (tipo de consola "su root") y luego crontab -e (sudo no es necesario en este caso).
Wolfgang
Bien. ¿No veo el punto de tu respuesta? Al escribir $ sudo crontab -e hizo el trabajo según lo informado por $ sudo crontab -l, es decir, la línea que describe el nuevo trabajo se ha agregado al cron de la raíz. Como tal, el trabajo no está presente en el cron del usuario, por ejemplo, $ crontab -l no muestra ningún trabajo cron agregado aquí.
Antonio
@WolfgangVogl usó "sudo" que funciona como se esperaba.
Alexis Wilke

Respuestas:

68

Si desea ejecutar un script como usuario normal :

crontab -e

Y agregue la línea:

07,37 * * * * /usr/bin/tunlrupdate.sh

Si quieres ejecutar tu script como root :

sudo crontab -e

Y agregue la misma línea:

07,37 * * * * /usr/bin/tunlrupdate.sh
Guillaume
fuente
@NineCattoRules Si no sueltas la salida, ¿qué ves?
Angelo Fuchs
@AngeloFuchs viejo comentario ... seguramente probé ese comando como root (en sudo crontab -elugar de crontab -e). O algo más, de todos modos funciona
NineCattoRules
10

Bueno, por fin la solución de trabajo. En el syslog vi lo repetitivo e intrigante:

CRON[18770]: (root) CMD (root /usr/bin/tunlrupdate.sh)

Eso suena como que la raíz no fue reconocida como un cmd. Como ya usé el cron de la raíz usando $ sudo /usr/bin/tunlrupdate.sh. Luego probé con el script original (corregido por un error en la fecha UNIX cmd:% m, que es mes, se usó durante minutos, que es% M) lo siguiente (que elimina la raíz de la línea cron):

$ sudo crontab -e
# check for updated Tunlr DNS every 30 minutes at the hour + 7 mn and hour + 37 mn
07,37 * * * * /usr/bin/tunlrupdate.sh

Esto resultó ser la solución final. [Aunque encontré decenas de literatura que indica la línea errónea con raíz en la línea cron. Eso fue un error].

Antonio
fuente
Buen punto Olli. Estoy de acuerdo contigo en eso. Como referencia, el usuario crontab se almacena en / var / spool / cron / crontabs / user-name o para root / var / spool / cron / crontabs / root. Consulte esta página askubuntu.com/questions/216692/where-is-the-user-crontab-stored La carpeta que contiene ya es y da el nombre del usuario.
Antonio
Bueno, no debería necesitar esa información, ya que solo debería editar los archivos crontab con el crontabcomando (excepto los archivos crontab en /etc).
Olli
1
@Antonio las puntuaciones con el campo de nombre de usuario solo se utilizan en /etc/crontab(el crontab de todo el sistema). Usando sudo crontab -eel que está trabajando crontab de root que por lo general se pueden encontrar en/var/spool/cron/crontabs
Matijs
2

Un "problema" con cron es la falta de variables de entorno (por razones obvias de seguridad). Probablemente te faltan PATH y HOME. Puede definirlos en el script directamente o en el archivo crontab.

# check for updated Tunlr DNS every 30 minutes at the hour + 7 mn and hour + 37 mn
PATH=/usr/bin
07,37 * * * * root /usr/bin/tunlrupdate.sh

Tendrá que probar hasta que todas las variables necesarias estén definidas como lo requiere el script.

Alexis Wilke
fuente
1
Esta es la única respuesta aquí que realmente funcionó para mí. Copié las declaraciones SHELL y PATH del /etc/crontabarchivo y las pegué en el sudo crontab -ey el comando se ejecutó como root sin ningún problema. ¡Gracias!
Terrance
0

Los mensajes de error de Cron generalmente se envían, por defecto, por correo electrónico. Puede verificar si hay correo electrónico para root sudo mail, o simplemente verificando el contenido de /var/mail/root, por ejemplo sudo less /var/mail/root.


Si los mensajes de correo electrónico no ayudan, también verifique /var/log/syslog:

sudo grep CRON /var/log/syslog

Como Alexis Wilke ya dijo, cron tiene un mecanismo diferente para establecer variables de entorno.

Tu script necesita

PATH=/sbin:/bin:/usr/bin

al crontab. HOMENo debería ser necesario. Debe usar rutas absolutas en sus scripts, por ejemplo, en /bin/datelugar de date. Puede encontrar rutas adecuadas para cada comando con which command_name, por ejemplo,

$ which date
/bin/date
Olli
fuente
Ejecutando su CRON grep sugerido en / var / log / syslog Obtuve el siguiente 11 de febrero 14:37:01 Marius-PC CRON [7826]: (root) CMD (root /usr/bin/tunlrupdate.sh) 11 de febrero 14: 37:01 Marius-PC CRON [7825]: (raíz) MAIL (enviado por correo 1 byte de salida; pero obtuvo el estado 0x00ff, # 012) 11 de febrero 14:39:01 Marius-PC CRON [7849]: (raíz) CMD ( [-x / usr / lib / php5 / maxlifetime] && [-d / var / lib / php5] && find / var / lib / php5 / -depth -mindepth 1 -maxdepth 1 -type f -cmin + $ (/ usr / lib / php5 / maxlifetime)! -execdir fuser -s {} 2> / dev / null \; -delete) Si agrego alguna definición para PATH en cron, ¿esto no afectará a mi sistema $ PATH?
Antonio
Esa salida dice que intentó enviar algo por correo electrónico pero falló. Eso significa que no recibirá ese mensaje de error /var/mail/root. Puedes arreglar eso o intentarloPATH=...
Olli
@Antonio, alternativamente, usa esta versión parcheada
Olli
Gracias. Sé que no configuré el correo electrónico del sistema y sabía que no se realizó. Ya había modificado el script para usar la ruta absoluta para cualquier función llamada. Lo último fue mi pregunta anterior: ¿una definición de RUTA dentro de crontab no alterará mi variable $ PATH del sistema?
Antonio
1
Mientras tanto, estaba ocupado corrigiendo un error en el formato de fecha del script original. Estaba usando% m (que es para el mes NO minuto) en lugar de% M ...
Antonio
0

Puede agregar esta línea en su secuencia de comandos. Entonces, después de verificar los registros cron y comprobar que su trabajo se ejecutó, puede obtener el mismo $ PATH que tenían los crontabs.

/bin/echo $PATH > /root/path.txt

Y probablemente lo mejor que puede hacer para diagnosticar problemas en los scripts cron es obtener todas las variables de entorno de SO con el comando env en su script. Así que solo agrega esta línea a tu script. Entonces puedes analizar la salidaallEvnVars.txt

/usr/bin/env > /root/allEvnVars.txt

Otro truco es dirigir la salida del script a algún lugar. Agregando el /root/log.log. De esta manera, toda la salida del script se mantendrá en/root/log.log

07,37 * * * * root /usr/bin/tunlrupdate.sh  > /root/log.log

También puede programar el script para ejecutar cada minuto para facilitar las pruebas y comprobaciones.

*/1 * * * * root /usr/bin/tunlrupdate.sh  > /root/log.log
Cassio Seffrin
fuente