Cómo hacer que CRON llame a las RUTA correctas

124

Estoy tratando de hacer que cron llame a las RUTA correctas. Cuando ejecuto un script de Python desde shell, el script funciona bien ya que usa las RUTA establecidas en bashrc pero cuando uso cron no todas las RUTA se usan desde bashrc. ¿Hay un archivo en el que pueda ingresar las RUTA para cron como bashrc o una forma de llamar a las RUTA desde bashrc?

Lo siento, no creo que haya redactado esto correctamente, puedo ejecutar el script correcto (lo que significa que la RUTA del script en crontab no es el problema aquí), es solo cuando ese script se está ejecutando, ejecuto una compilación y utiliza el CAMINOS establecidos .bashrc. Cuando ejecuto el script cuando estoy conectado, las .bashrcPATHs se activan. Dado que cron no se ejecuta en un shell por decirlo, no se activa .bashrc. ¿Hay alguna manera de hacer esto sin tener que escribir un contenedor de script bash?

chrissygormley
fuente
También eche un vistazo a la sugerencia dada aquí sobre cómo hacer que la configuración de
bashrc
2
El comando mágico, simple y correcto para incluir su perfil en el entorno actual es source /etc/profileque debe comer .bashrcy muchas otras cosas potencialmente faltantes para usted. El abastecimiento explícito de perfiles se vuelve bastante útil si desea que algunos scripts se ejecuten "de forma independiente", también protege de entornos extraños y, por lo tanto ...
exa
1
@exa +100 Esto hace que los shscripts llamados por crontab funcionen. Puede confirmar que actualiza la ruta agregando un trabajo como * * * * * echo $PATH > ~/crontab_path.txty revisando el archivo después de un minuto.
geoteoría

Respuestas:

177

He utilizado /etc/crontab. Solía viy entré en los caminos que necesitaba en este archivo y corriendo como root. El crontab normal sobrescribe las RUTA que ha configurado. Un buen tutorial sobre cómo hacer esto .

El archivo cron de todo el sistema se ve así:

This has the username field, as used by /etc/crontab.
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file.
# This file also has a username field, that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user   command
42 6 * * *   root    run-parts --report /etc/cron.daily
47 6 * * 7   root    run-parts --report /etc/cron.weekly
52 6 1 * *   root    run-parts --report /etc/cron.monthly
01 01 * * 1-5 root python /path/to/file.py
chrissygormley
fuente
17
Esto funciona con crontab -e a nivel de usuario y también es más seguro de esa manera.
Robert Brisita
2
¿Puedo usar bash en lugar de sh?
qed
1
Es extraño (para mí) que la RUTA predeterminada establecida en / etc / crontab como se muestra en @chrissygormley, y también establecida en mi (Ubuntu) crontab, es diferente de la ruta en / etc / environment, específicamente pone / sbin y / bin delante de / usr / sbin y / usr / bin. Ahora he cambiado esto en mi / etc / crontab para que sea el mismo que el entorno del usuario.
scoobydoo
No funciona para mí ... Estoy enviando contenido cron a un archivo. Cron se ejecuta, el archivo crea pero no pone ningún contenido en él.
Volatil3
2
Parece que no todas las rutas establecidas /etc/crontabestán disponibles para cron cuando se ejecuta como root en Ubuntu 14.04. ( sudo crontab -e)
David Oliver el
50

Lo más probable es que cron se ejecute en un entorno muy escaso. Verifique las variables de entorno que cron está utilizando agregando un trabajo ficticio que se vuelca enven un archivo como este:

* * * * * env > env_dump.txt

Compare eso con la salida de enven una sesión de shell normal.

Puede anteponer sus propias variables de entorno al crontab local definiéndolas en la parte superior de su crontab.

Aquí hay una solución rápida para anteponer $PATHal crontab actual:

# echo PATH=$PATH > tmp.cron
# echo >> tmp.cron
# crontab -l >> tmp.cron
# crontab tmp.cron

El crontab resultante se verá similar a la respuesta de chrissygormley, con PATH definido antes de las reglas de crontab.

joemaller
fuente
22

Debes poner caminos completos en tu crontab. Esa es la opción más segura.
Si no desea hacerlo, puede colocar un script de envoltura alrededor de sus programas y establecer la RUTA allí.

p.ej

01 01 * * * command

se convierte en:

01 01 * * * /full/path/to/command

Además, todo lo que se llame crondebe tener mucho cuidado con los programas que ejecuta, y probablemente establecer su propia elección para la PATHvariable.

EDITAR:

Si no sabe dónde está el comando que desea ejecutar which <command>desde su shell y le indicará la ruta.

EDIT2:

Entonces, una vez que su programa se está ejecutando, lo primero que debe hacer es establecer PATHy cualquier otra variable requerida (por ejemplo LD_LIBRARY_PATH) a los valores que se requieren para que se ejecute el script.
Básicamente, en lugar de pensar cómo modificar el entorno cron para que sea más adecuado para su programa / secuencia de comandos, haga que su secuencia de comandos maneje el entorno que se le proporciona, configurando uno apropiado cuando se inicie.

Douglas Leeder
fuente
1
si está en tu camino, usa "qué comando" y te dará el camino completo
Paul Whelan
@ Douglas Leeder: cuando dice poner la ruta completa en cron, ¿quiere decir ponerlo en crontab u otro archivo? Si es así, ¿cómo lo haría si el comando cron es: '01 01 * * * command '? Gracias
chrissygormley
@chrissygormley - Sí crontab.
Douglas Leeder
Lo siento, debe haber alguna confusión. He reformulado la pregunta anterior.
chrissygormley
16

Establecer PATH justo antes de la línea de comando en mi crontab funcionó para mí:

* * * * * PATH=$PATH:/usr/local/bin:/path/to/some/thing
mirra
fuente
Prefiero de esta manera. o especifique la ruta completa de la secuencia de comandos.
zw963
55
No creo que el camino siga creciendo, cada vez que se ejecute será un nuevo entorno, con una nueva copia de PATH ...
jjcf89
Puede confirmar que @ jjcf89 es correcto, PATH es nuevo en cada ejecución.
electrovir
14

Agregar una definición de RUTA en el crontab de usuario con los valores correctos ayudará ... He llenado el mío con solo:

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

Y es suficiente para que todos mis scripts funcionen ... Incluya cualquier ruta personalizada allí si es necesario.

Treviño
fuente
1
Para un crontab de usuario, esta debería ser la respuesta correcta. No todos en un sistema pueden editar /etc/crontab. Esta es la respuesta más fácil a nivel de usuario. Buen trabajo @ Treviño. Vota esto si estás de acuerdo.
frederickjh
14

Haga que sus variables trabajen para usted, esto permitirá el acceso t

Defina su RUTA en /etc/profile.d/*.sh

Variables de entorno de todo el sistema

Los archivos con la extensión .sh en el directorio /etc/profile.d se ejecutan cada vez que se ingresa un shell de inicio de sesión bash (por ejemplo, al iniciar sesión desde la consola o sobre ssh), así como por el DisplayManager cuando se carga la sesión de escritorio.

Por ejemplo, puede crear el archivo /etc/profile.d/myenvvars.sh y establecer variables como esta:

export JAVA_HOME=/usr/lib/jvm/jdk1.7.0
export PATH=$PATH:$JAVA_HOME/bin

¡Ejecute crontab con la opción de inicio de sesión!

CRONTAB ejecuta script o comando con variables de entorno

0 9 * * * cd /var/www/vhosts/foo/crons/; bash -l -c 'php -f ./download.php'
0 9 * * * cd /var/www/vhosts/foo/crons/; bash -l -c download.sh
Artistan
fuente
11

Problema

Su script funciona cuando lo ejecuta desde la consola, pero falla en cron.

Porque

Su crontab no tiene las variables de ruta correctas (y posiblemente shell)

Solución

Agregue su shell y ruta actual al crontab

Guión para hacerlo por ti

#!/bin/bash
#
# Date: August 22, 2013
# Author: Steve Stonebraker
# File: add_current_shell_and_path_to_crontab.sh
# Description: Add current user's shell and path to crontab
# Source: http://brakertech.com/add-current-path-to-crontab
# Github: hhttps://github.com/ssstonebraker/braker-scripts/blob/master/working-scripts/add_current_shell_and_path_to_crontab.sh

# function that is called when the script exits (cleans up our tmp.cron file)
function finish { [ -e "tmp.cron" ] && rm tmp.cron; }

#whenver the script exits call the function "finish"
trap finish EXIT

########################################
# pretty printing functions
function print_status { echo -e "\x1B[01;34m[*]\x1B[0m $1"; }
function print_good { echo -e "\x1B[01;32m[*]\x1B[0m $1"; }
function print_error { echo -e "\x1B[01;31m[*]\x1B[0m $1"; }
function print_notification { echo -e "\x1B[01;33m[*]\x1B[0m $1"; }
function printline { 
  hr=-------------------------------------------------------------------------------------------------------------------------------
  printf '%s\n' "${hr:0:${COLUMNS:-$(tput cols)}}"
}
####################################
# print message and exit program
function die { print_error "$1"; exit 1; }

####################################
# user must have at least one job in their crontab
function require_gt1_user_crontab_job {
        crontab -l &> /dev/null
        [ $? -ne 0 ] && die "Script requires you have at least one user crontab job!"
}


####################################
# Add current shell and path to user's crontab
function add_shell_path_to_crontab {
    #print info about what's being added
    print_notification "Current SHELL: ${SHELL}"
    print_notification "Current PATH: ${PATH}"

    #Add current shell and path to crontab
    print_status "Adding current SHELL and PATH to crontab \nold crontab:"

    printline; crontab -l; printline

    #keep old comments but start new crontab file
    crontab -l | grep "^#" > tmp.cron

    #Add our current shell and path to the new crontab file
    echo -e "SHELL=${SHELL}\nPATH=${PATH}\n" >> tmp.cron 

    #Add old crontab entries but ignore comments or any shell or path statements
    crontab -l | grep -v "^#" | grep -v "SHELL" | grep -v "PATH" >> tmp.cron

    #load up the new crontab we just created
    crontab tmp.cron

    #Display new crontab
    print_good "New crontab:"
    printline; crontab -l; printline
}

require_gt1_user_crontab_job
add_shell_path_to_crontab

Fuente

https://github.com/ssstonebraker/braker-scripts/blob/master/working-scripts/add_current_shell_and_path_to_crontab.sh

Salida de muestra

Salida de ejemplo add_curent_shell_and_path_to_crontab.sh

freno de mano
fuente
3

En mi cron AIX recoge sus variables ambientales de / etc / environment ignorando lo que se establece en el .profile.

Editar: También revisé un par de cuadros de Linux de varias edades y parece que también tienen este archivo, por lo que probablemente no sea específico de AIX.

Lo comprobé utilizando la sugerencia cron de joemaller y comprobando la salida antes y después de editar la variable PATH en / etc / environment.

Van Amburg
fuente
3

Si no desea tener que hacer las mismas ediciones en varios lugares, haga esto aproximadamente:

* * * * * . /home/username/.bashrc && yourcommand all of your args

Los . espacio y luego la ruta a .bashrc y el comando && son la magia para lograr que los cambios de su entorno se ejecuten en el shell bash en ejecución. También, si realmente quieres que el shell sea bash, es una buena idea tener una línea en tu crontab:

SHELL=/bin/bash

Espero que ayude a alguien!

Wade Chandler
fuente
2

El entorno predeterminado para los trabajos cron es muy escaso y puede ser muy diferente del entorno en el que desarrolla sus scripts de Python. Para un script que pueda ejecutarse en cron, cualquier entorno del que dependa debe establecerse explícitamente. En el propio archivo cron, incluya rutas completas a los ejecutables de Python y a sus scripts de Python.

multitud
fuente
2

Sé que esto ya ha sido respondido, pero pensé que sería útil para algunos. Tuve un problema similar que resolví recientemente ( encontrado aquí ) y aquí están los aspectos más destacados de los pasos que tomé para responder esta pregunta:

  1. asegúrese de tener las variables que necesita en PYTHONPATH (que se encuentra aquí y aquí y para obtener más información aquí) dentro del .profile o .bash_profile para cualquier shell en el que desee probar su script para asegurarse de que funciona.

  2. edite su crontab para incluir los directorios necesarios para ejecutar su script en un trabajo cron (que se encuentra aquí y aquí)

    a) asegúrese de incluir el directorio raíz en la variable PATH (.) como se explica aquí (básicamente, si está ejecutando un ejecutable con su comando, debe poder encontrar la raíz o el directorio donde está almacenado el ejecutable) y probablemente estos (/ sbin: / bin: / usr / sbin: / usr / bin)

  3. en su archivo crontab, cree un cronjob que cambiará el directorio al directorio donde ha ejecutado correctamente el script antes (es decir, Usuarios / usuario / Documentos / foo)

    a) Esto se verá así:

    * * * * cd /Users/user/Documents/foo; bar -l doSomething -v 
    
derigible
fuente
2

@Trevino: tu respuesta me ayudó a resolver mi problema. Sin embargo, para un principiante, tratar de dar un enfoque paso a paso.

  1. Obtenga su instalación actual de java a través de $ echo $JAVA_HOME
  2. $ crontab -e
  3. * * * * * echo $PATH- esto le permite comprender cuál es el valor de RUTA que está utilizando crontab en la actualidad. Ejecute crontab y tome el valor $ PATH utilizado por crontab.
  4. Ahora edite crontab nuevamente para configurar la ruta java bin deseada: a) crontab -e; b) PATH=<value of $JAVA_HOME>/bin:/usr/bin:/bin(es una ruta de muestra); c) ahora su trabajo / script programado como */10 * * * * sh runMyJob.sh &; d) eliminar echo $PATHde crontab ya que no es necesario ahora.
Ram Dwivedi
fuente
2

Establezca la RUTA requerida en su cron

crontab -e

Editar: Presione i

PATH=/usr/local/bin:/usr/local/:or_whatever

10 * * * * your_command

Guardar y Salir :wq

Yogesh Yadav
fuente
1

La solución más simple que he encontrado se ve así:

* * * * * root su -l -c command

Este ejemplo se invoca sucomo usuario root e inicia el shell con el entorno completo del usuario, incluido $ PATH, configurado como si estuvieran conectados. Funciona igual en diferentes distribuciones, es más confiable que el abastecimiento de .bashrc (que no ha funcionado para yo) y evita codificar rutas específicas que pueden ser un problema si proporciona un ejemplo o una herramienta de configuración y no sabe qué distribución o distribución de archivos tiene el sistema del usuario.

También puede especificar el nombre de usuario después susi desea un usuario diferente al root, pero probablemente debería dejar el rootparámetro antes del sucomando ya que esto garantiza que sutenga los privilegios suficientes para cambiar a cualquier usuario que especifique.


fuente
-3

En caso de que utilice webmin, estos son los pasos para configurar el PATHvalor:

System
  -> Scheduled Cron Jobs
       -> Create a new environment variable
            -> For user: <Select the user name>
            -> Variable name: PATH
            -> Value: /usr/bin:/bin:<your personal path>
            -> Add environment variable: Before all Cron jobs for user
Peter VARGA
fuente