2010-07-09 14 views
21

No tuve mucha suerte buscando en Google esta pregunta y pensé en publicarla en SF, pero en realidad parece una pregunta de desarrollo. Si no, siéntase libre de migrar.¿Puede una secuencia de comandos bash decir si se está ejecutando a través de cron?

Entonces, tengo un script que se ejecuta a través de cron todas las mañanas a eso de las 3 a.m. También ejecuto las mismas secuencias de comandos manualmente a veces. El problema es que cada vez que ejecuto mi script manualmente y falla, me envía un correo electrónico; aunque puedo mirar la salida y ver el error en la consola.

¿Hay alguna manera para que el script bash diga que se está ejecutando a través de cron (quizás usando whoami) y solo envía el correo electrónico si es así? Me encantaría dejar de recibir correos electrónicos cuando realizo mis pruebas ...

+1

¿Está enviando correos electrónicos desde su script? ¿No cron por salida de correo predeterminada al propietario del crontab? – Cascabel

+0

Estoy enviando correos electrónicos desde adentro, pero necesitaba enviar la salida.No me di cuenta de que cron hizo esto. –

+0

Oiga, use el correo electrónico saliente REAL como en 'correo', no solo usando el sistema de correo electrónico de Unix. – gbtimmon

Respuesta

23

puede probar "tty" para ver si es operado por un terminal o no. eso no le dirá que es específicamente ejecutado por cron, pero puede decir si es "no un usuario como un aviso".

También puede obtener su parent-pid y seguirlo por el árbol para buscar cron, aunque es un poco torpe.

+13

¡Gracias por esta respuesta! La primera respuesta que escogí no era en realidad lo que quería (caparazón interactivo). Debido a su respuesta, encontré lo que realmente necesitaba haciendo una búsqueda en Google "bash tty test". Básicamente, llama a 'tty -s' en tu script y luego marca' $? ': Si es 0, estás en un tty, si es mayor que 0, no lo eres. –

+1

'tty' es un comando externo (se concede parte de coreutils, pero sigue siendo una bifurcación), hay varias maneras de usar cosas incorporadas para hacer lo mismo que se describe en https://unix.stackexchange.com/a/46801/103306 –

9

¿Por qué no tener un argumento de línea de comandos que es -t para la prueba o -c para cron.

O mejor aún:

[email protected]

Si no se especifica, no envíe un correo electrónico.

+0

Dejo caer el script en /etc/cron.daily para que no pueda agregar argumentos fácilmente, pero creo que podría moverlo a un crontab real. Solo esperaba no tener que agregar argumentos o establecer variables de entorno en la línea de comandos ... aunque: establecer una variable de entorno de PRUEBA en mi archivo .bashrc haría el truco. Gracias por las sugerencias. –

+0

No hay problema con poner myscript.sh arg1 arg2 arg3 en un archivo de script en /etc/cron.daily. Normalmente no pongo mi script/archivo binario directamente en los directorios /etc/cron.*. Normalmente dejo eso para los scripts que ejecutan el trabajo cron (puede ser otro script). Entonces puedo escribir mi script más genérico y utilizable en otros entornos. –

8

Aquí hay dos opciones diferentes para usted:

  • tomar el correo electrónico fuera de su script/programa y dejar que cron manejarlo. Si configura la variable MAILTO en su crontab, cron enviará todo lo impreso a esa dirección de correo electrónico. por ejemplo:

    [email protected] 
    # run five minutes after midnight, every day 
    5 0 * * *  $HOME/bin/daily.job 
    
  • Establecer una variable de entorno en su crontab que se utiliza para determinar si se ejecuta bajo cron. por ejemplo:

    THIS_IS_CRON=1 
    # run five minutes after midnight, every day 
    5 0 * * *  $HOME/bin/daily.job 
    

    y en su script algo así como

    if [ -n "$THIS_IS_CRON" ]; then echo "I'm running in cron"; else echo "I'm not running in cron"; fi 
    
6

Sé que la pregunta es viejo, pero me encontré con el mismo problema. Este fue mi solución:

CRON=$(pstree -s $$ | grep -q cron && echo true || echo false) 

entonces prueba con

if $CRON 
then 
    echo "Being run by cron" 
else 
    echo "Not being run by cron" 
fi 

misma idea como la que se menciona @eruciform - sigue su PID el árbol de procesos comprobación de cron.

Nota: Esta solución solo funciona específicamente para cron, a diferencia de algunas de las otras soluciones, que funcionan siempre que el script se ejecuta de forma no interactiva.

+0

Me encanta la simplicidad de establecer var en true o false (comandos), de modo que si $ CRON funciona (a diferencia del habitual if ["$ CRON"]), pero tenga en cuenta que si $ CRON termina indefinido por alguna razón, la versión dada se evalúa como verdadera. No está bien. –

+0

También me gustó la idea, pero también veo el riesgo de tener retornos indefinidos. Terminé con una versión ligeramente modificada, que parece funcionar muy bien en mi opinión: CRON = "$ (pstree -s $$ | grep -c cron)" Para que pueda verificar si $ CRON es 1 o 0. – frank42

4

Lo que funciona para mí es marcar $TERM. Bajo cron es "tonto" pero bajo un caparazón es algo más.Utilice el comando set en su terminal, a continuación, en un cron-escritura y comprobar que funciona

if [ "dumb" == "$TERM" ] 
then 
    echo "cron" 
else 
    echo "term" 
fi 
+1

También verificaría si $ TERM no está vacío. '[-n" $ TERM "-a" $ TERM "==" tonto "] && eco" interactivo "|| echo "cron o no tty" ' – Andor

6

tuve un problema similar. Lo resolví comprobando si stdout era un TTY. Esta es una comprobación para ver si la escritura se ejecuta en modo interactivo:

if [ -t 1 ] ; then 
    echo "interacive mode"; 
else 
    #send mail 
fi 

me dieron esto desde: How to detect if my shell script is running through a pipe?

El retorno de ensayo -t cierto si descriptor de archivo es abierto y se refiere a un terminal. '1' es stdout.

4

Me gustaría sugerir una nueva respuesta a esta pregunta tan votada. Esto funciona solo en sistemas systemd con loginctl (por ejemplo, Ubuntu 14.10+, RHEL/CentOS 7+), pero es capaz de dar una respuesta mucho más autoritaria que las soluciones presentadas anteriormente.

service=$(loginctl --property=Service show-session $(</proc/self/sessionid)) 
if [[ ${service#*=} == 'crond' ]]; then 
    echo "running in cron" 
fi 

En resumen: cuando se utiliza con systemd, crond (como sshd y otros) crea un nuevo session cuando se inicia un trabajo para un usuario. Esta sesión tiene una identificación que es única para todo el tiempo de actividad de la máquina. Cada sesión tiene algunas propiedades, una de las cuales es el nombre del servicio que la inició. loginctl puede decirnos el valor de esta propiedad, que será "crond" si y solo si la sesión fue realmente iniciada por crond.


ventajas sobre el uso de variables de entorno:

  • No hay necesidad de modificar las entradas de cron para agregar invocaciones especiales o variables de entorno
  • No hay posibilidad de un proceso intermedio modificar las variables de entorno para crear un falso positivo o falso negativo

Ventajas sobre las pruebas de tty:

  • No hay falsos positivos en las tuberías, los scripts de arranque, etc

Ventajas sobre el control de la árbol de procesos:

  • No hay falsos positivos de los procesos que también tienen crond en su nombre
  • n falsos negativos si el guión no es reconocido
0

También me ha gustado idea de Tal, pero también ve el riesgo de tener retornos indefinidos. Terminé con una versión ligeramente modificada, que parece funcionar muy suave en mi opinión:

CRON="$(pstree -s $$ | grep -c cron)"

para que pueda comprobar por $ CRON ser 1 ó 0 en cualquier momento.

Cuestiones relacionadas