web-dev-qa-db-fra.com

Comment faire en sorte que CRON appelle les PATH corrects

J'essaye de faire en sorte que cron appelle les PATH corrects. Lorsque j'exécute un script Python à partir de Shell, le script fonctionne correctement car il utilise les PATH définis dans bashrc, mais lorsque j'utilise cron, tous les PATH ne sont pas utilisés depuis bashrc. Existe-t-il un fichier dans lequel je peux entrer les PATH pour cron comme bashrc ou un moyen d'appeler les PATH depuis bashrc?

Désolé, je ne pense pas avoir correctement formulé cela, je peux obtenir le bon script à exécuter (ce qui signifie que le PATH du script dans crontab n'est pas le problème ici), CHEMINS définis dans .bashrc. Lorsque j'exécute le script lorsque je suis connecté, les chemins .bashrc sont extraits. Puisque cron ne s'exécute pas dans un shell, il ne récupère pas non plus le .bashrc. Existe-t-il un moyen d’insérer cela sans avoir à écrire un wrapper de script bash?

104
chrissygormley

J'ai utilisé /etc/crontab. J'ai utilisé vi et entré dans les chemins d'accès dont j'avais besoin dans ce fichier et je l'ai exécuté en tant que root. La crontab normale écrase les chemins PATH que vous avez configurés. Un bon tutoriel sur la façon de faire cela .

Le fichier cron à l'échelle du système ressemble à ceci:

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
146
chrissygormley

Très probablement, cron fonctionne dans un environnement très clairsemé. Vérifiez les variables d'environnement utilisées par cron en ajoutant un travail fictif qui copie env dans un fichier comme celui-ci:

* * * * * env > env_dump.txt

Comparez cela avec le résultat de env dans une session Shell normale.

Vous pouvez ajouter vos propres variables d’environnement à la crontab locale en les définissant en haut de votre crontab.

Voici une solution rapide pour ajouter $PATH à la crontab actuelle:

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

La crontab résultante ressemblera à la réponse de chrissygormley, avec PATH défini avant les règles de la crontab. 

45
joemaller

Vous devriez mettre des chemins complets dans votre crontab. C'est l'option la plus sûre.
Si vous ne voulez pas faire cela, vous pouvez mettre un script wrapper autour de vos programmes et y placer le PATH.

par exemple.

01 01 * * * command

devient:

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

De même, tout ce qui est appelé depuis cron doit faire très attention aux programmes qu’il exécute et définir probablement son propre choix pour la variable PATH.

MODIFIER:

Si vous ne savez pas où la commande consiste à exécuter which <command> à partir de votre shell, il vous indiquera le chemin. 

EDIT2:

Ainsi, une fois que votre programme est en cours d'exécution, la première chose à faire est de définir PATH et toute autre variable requise (par exemple, LD_LIBRARY_PATH) sur les valeurs requises pour l'exécution du script.
Au lieu de penser à la modification de l’environnement cron pour l’adapter davantage à votre programme/script, faites en sorte que votre script gère l’environnement qui lui est attribué en définissant un environnement approprié au démarrage.

19
Douglas Leeder

Faites que vos variables fonctionnent pour vous, cela permettra l'accès

Définissez votre PATH dans /etc/profile.d/*.sh

Variables d'environnement à l'échelle du système

Les fichiers portant l'extension .sh dans le répertoire /etc/profile.d sont exécutés chaque fois qu'un shell de connexion bash est entré (par exemple, lors de la connexion à partir de la console ou via ssh), ainsi que par DisplayManager lors du chargement de la session de bureau.

Vous pouvez par exemple créer le fichier /etc/profile.d/myenvvars.sh et définir des variables comme ceci:

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

Exécute la crontab avec l'option de connexion!

Script ou commande d'exécution CRONTAB avec des variables d'environnement

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
14
Artistan

Définir PATH juste avant la ligne de commande dans ma crontab a fonctionné pour moi:

* * * * * PATH=$PATH:/usr/local/bin:/path/to/some/thing
13
myrho

Problème

Votre script fonctionne lorsque vous l'exécutez à partir de la console mais échoue dans cron.

Cause

Votre crontab n'a pas les bonnes variables de chemin (et éventuellement Shell)

Solution

Ajoutez votre shell actuel et cheminez la crontab

Script pour le faire pour vous

#!/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

La source

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

Exemple de sortie

add_curent_Shell_and_path_to_crontab.sh example output

9
brakertech

Ajouter une définition de PATH dans la crontab de l'utilisateur avec les valeurs correctes aidera ....... J'ai rempli la mienne avec juste:

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

Et cela suffit pour que tous mes scripts fonctionnent ... Incluez un chemin personnalisé là-bas si vous en avez besoin.

9
Treviño

Sur mon AIX, cron sélectionne ses variables d'environnement dans/etc/environment en ignorant ce qui est défini dans le fichier .profile. 

Edit: J'ai également extrait deux boîtes Linux de différents âges. Celles-ci semblent également contenir ce fichier. Ce n'est donc probablement pas spécifique à AIX. 

J'ai vérifié cela en utilisant la suggestion cron de joemaller et en vérifiant la sortie avant et après l'édition de la variable PATH dans/etc/environment.

2
Van Amburg

L'environnement par défaut des tâches cron est très clairsemé et peut être très différent de l'environnement dans lequel vous développez vos scripts python. Pour un script pouvant être exécuté dans cron, tout environnement sur lequel vous dépendez doit être défini explicitement. Dans le fichier cron lui-même, incluez des chemins complets vers les exécutables python et vos scripts python.

2
mob

Je sais que cela a déjà été répondu, mais je pensais que le sien serait utile à certains. J'ai eu un problème similaire que j'ai récemment résolu ( trouvé ici ) et voici les points saillants des étapes que j'ai entreprises pour répondre à cette question:

  1. assurez-vous que vous avez les variables dont vous avez besoin dans PYTHONPATH (trouvées ici et ici et pour plus d'informations ici) à l'intérieur du fichier .profile ou .bash_profile de tout shell dans lequel vous souhaitez tester votre script pour vous assurer qu'il fonctionne.

  2. éditez votre crontab pour inclure les répertoires nécessaires à l'exécution de votre script dans un travail cron (trouvé ici et ici)

    a) assurez-vous d’inclure le répertoire racine dans la variable PATH (.) comme expliqué ici (essentiellement si vous exécutez un fichier exécutable avec votre commande, vous devez être en mesure de trouver la racine ou le répertoire dans lequel est stocké le fichier exécutable) et probablement ces derniers. (/ sbin:/bin:/usr/sbin:/usr/bin)

  3. dans votre fichier crontab, créez un travail cron qui changera de répertoire en répertoire où vous avez déjà exécuté le script avec succès (à savoir Utilisateurs/utilisateur/Documents/foo)

    a) Cela ressemblera à ceci:

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

@Trevino: votre réponse m'a aidé à résoudre mon problème. Cependant, pour un débutant, essayez de donner une approche étape par étape. 

  1. Obtenez votre installation actuelle de Java via $ echo $Java_HOME
  2. $ crontab -e
  3. * * * * * echo $PATH - ceci vous permet de comprendre quelle est la valeur de PATH utilisée actuellement par crontab. Exécutez crontab et récupérez la valeur $ PATH utilisée par crontab.
  4. Maintenant, éditez à nouveau crontab pour définir votre chemin de corbeille Java souhaité: a) crontab -e; b) PATH=<value of $Java_HOME>/bin:/usr/bin:/bin (c'est un exemple de chemin); c) maintenant votre travail/script planifié tel que */10 * * * * sh runMyJob.sh &; d) retirez echo $PATH de crontab car ce n’est pas nécessaire maintenant.
1
Ram Dwivedi

La solution de contournement la plus simple que j'ai trouvée ressemble à ceci:

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

Cet exemple appelle su en tant qu'utilisateur root et démarre le shell avec l'environnement complet de l'utilisateur, y compris $ PATH, défini comme s'il était connecté. Il fonctionne de la même manière sur différentes distributions, il est plus fiable que le sourcing .bashrc (qui n'a pas fonctionné pour moi) et évite de coder en dur des chemins spécifiques qui peuvent poser problème si vous fournissez un exemple ou un outil de configuration et que vous ne savez pas quelle distribution ou quelle disposition de fichier sur le système de l'utilisateur.

Vous pouvez également spécifier le nom d'utilisateur après su si vous souhaitez utiliser un autre utilisateur que root, mais vous devez probablement laisser le paramètre root avant la commande su, car cela garantit que su dispose des privilèges suffisants pour basculer vers l'utilisateur de votre choix.

1
tasket

Si vous ne voulez pas avoir à faire les mêmes modifications à différents endroits, alors procédez comme suit:

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

Le . space, puis le chemin d'accès à .bashrc et la commande && sont la magie pour transférer les modifications de votre environnement dans le shell bash en cours d'exécution. Aussi, si vous voulez vraiment que le shell soit bash, c'est une bonne idée d'avoir une ligne dans votre crontab:

Shell=/bin/bash

J'espère que ça aide quelqu'un!

1
Wade Chandler

Définissez le chemin requis dans votre cron 

crontab -e

Edit: Press i

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

10 * * * * your_command

Sauvegarder et quitter :wq

0
shiva