web-dev-qa-db-fra.com

Où puis-je définir les variables d'environnement que crontab utilisera?

J'ai une crontab en marche toutes les heures. L'utilisateur qui l'exécute a un environnement variable dans le .bash_profile qui fonctionne lorsque l'utilisateur exécute le travail à partir du terminal. Toutefois, il est évident que ceux-ci ne sont pas récupérés par crontab lors de son exécution.

J'ai essayé de les placer dans .profile et .bashrc mais ils ne semblent toujours pas avoir été captés. Est-ce que quelqu'un sait où je peux mettre les vars d'environnement que crontab peut prendre?

243
James

Demandez à 'cron' d'exécuter un script Shell qui définit l'environnement avant d'exécuter la commande.

Toujours.

#   @(#)$Id: crontab,v 4.2 2007/09/17 02:41:00 jleffler Exp $
#   Crontab file for Home Directory for Jonathan Leffler (JL)
#-----------------------------------------------------------------------------
#Min     Hour    Day     Month   Weekday Command
#-----------------------------------------------------------------------------
0        *       *       *       *       /usr/bin/ksh /work1/jleffler/bin/Cron/hourly
1        1       *       *       *       /usr/bin/ksh /work1/jleffler/bin/Cron/daily
23       1       *       *       1-5     /usr/bin/ksh /work1/jleffler/bin/Cron/weekday
2        3       *       *       0       /usr/bin/ksh /work1/jleffler/bin/Cron/weekly
21       3       1       *       *       /usr/bin/ksh /work1/jleffler/bin/Cron/monthly

Les scripts dans ~/bin/Cron sont tous des liens vers un seul script, 'runcron', qui ressemble à:

:       "$Id: runcron.sh,v 2.1 2001/02/27 00:53:22 jleffler Exp $"
#
#       Commands to be performed by Cron (no debugging options)

#       Set environment -- not done by cron (usually switches HOME)
. $HOME/.cronfile

base=`basename $0`
cmd=${REAL_HOME:-/real/home}/bin/$base

if [ ! -x $cmd ]
then cmd=${HOME}/bin/$base
fi

exec $cmd ${@:+"$@"}

(Écrit en utilisant une ancienne norme de codage - de nos jours, j'utiliserais un Shebang '#!' Au début.)

Le fichier "~/.cronfile" est une variante de mon profil destinée à être utilisée par cron - rigoureusement non interactif et ne faisant pas écho pour être bruyant. Vous pouvez organiser à la place le fichier .profile, etc. (Le contenu de REAL_HOME est un artefact de mon environnement - vous pouvez prétendre qu'il en va de même pour $ HOME.)

Ainsi, ce code lit l'environnement approprié, puis exécute la version non cron de la commande à partir de mon répertoire personnel. Ainsi, par exemple, ma commande "jour de la semaine" ressemble à ceci:

:       "@(#)$Id: weekday.sh,v 1.10 2007/09/17 02:42:03 jleffler Exp $"
#
#       Commands to be done each weekday

# Update ICSCOPE
n.updics

La commande 'daily' est plus simple:

:       "@(#)$Id: daily.sh,v 1.5 1997/06/02 22:04:21 johnl Exp $"
#
#       Commands to be done daily

# Nothing -- most things are done on weekdays only

exit 0
81
Jonathan Leffler

Vous pouvez définir des variables d'environnement dans la crontab elle-même lors de l'exécution de crontab -e à partir de la ligne de commande.

LANG=nb_NO.UTF-8
LC_ALL=nb_NO.UTF-8
# m h  dom mon dow   command

* * * * * sleep 5s && echo "yo"

Cette fonctionnalité n'est disponible que pour certaines implémentations de cron. Ubuntu et Debian utilisent actuellement vixie-cron , ce qui permet de les déclarer dans le fichier crontab (également GNU mcron ).

Archlinux et RedHat utilise cronie qui n'autorise pas les variables d'environnement. à déclarer et jettera des erreurs de syntaxe dans le fichier cron.log. La solution de contournement peut être effectuée par entrée:

# m h  dom mon dow   command
* * * * * export LC_ALL=nb_NO.UTF-8; sleep 5s && echo "yo"
226
carestad

J'ai encore une solution à ce problème:

0 5 * * * . $HOME/.profile; /path/to/command/to/run

Dans ce cas, toutes les variables d’environnement définies dans votre fichier $HOME/.profile seront sélectionnées.

Bien sûr, $HOME n'est pas défini, vous devez le remplacer par le chemin complet de votre $HOME.

134
Vishal

La définition de vars dans /etc/environment a également fonctionné pour moi dans Ubuntu. A partir de 12.04, les variables dans /etc/environment sont chargées pour cron.

48
baxeico

L’exemple @carestad, que je trouve plus facile, consiste à exécuter le script avec cron et à inclure l’environnement dans le script.

Dans le fichier crontab -e:

Shell=/bin/bash

*/1 * * * * $HOME/cron_job.sh

Dans le fichier cron_job.sh:

#!/bin/bash
source $HOME/.bash_profile
some_other_cmd

Toute commande après la source de .bash_profile aura votre environnement comme si vous vous étiez connecté.

22
Robert Brisita

Si vous démarrez les scripts que vous exécutez via cron avec:

#!/bin/bash -l

Ils devraient récupérer vos variables d’environnement ~/.bash_profile

22
breizhmg

Pour moi, je devais définir la variable d'environnement pour une application PHP. Je l'ai aimé en ajoutant le code suivant à ma crontab.

$ Sudo  crontab -e

crontab:

ENVIRONMENT_VAR=production

* * * * * /home/deploy/my_app/cron/cron.doSomethingWonderful.php

et dans doSomethingWonderful.php, je pourrais obtenir la valeur d'environnement avec:

<?php     
echo $_SERVER['ENVIRONMENT_VAR']; # => "production"

J'espère que ça aide!

14
karlingen

Tout ce que vous définissez dans crontab sera disponible dans les tâches cron, à la fois directement et en utilisant les variables dans les scripts.

Utilisez-les dans la définition du cronjob

Vous pouvez configurer crontab pour qu'il définisse des variables qui seront ensuite utilisées par cronjob:

$ crontab -l
myvar="hi man"
* * * * * echo "$myvar. date is $(date)" >> /tmp/hello

Maintenant, le fichier /tmp/hello montre des choses comme:

$ cat /tmp/hello 
hi man. date is Thu May 12 12:10:01 CEST 2016
hi man. date is Thu May 12 12:11:01 CEST 2016

Utilisez-les dans le script exécuté par cronjob

Vous pouvez configurer crontab pour qu'il définisse des variables que les scripts peuvent ensuite utiliser:

$ crontab -l
myvar="hi man"
* * * * * /bin/bash /tmp/myscript.sh

Et dites script /tmp/myscript.sh est comme ceci:

echo "Now is $(date). myvar=$myvar" >> /tmp/myoutput.res

Il génère un fichier /tmp/myoutput.res montrant:

$ cat /tmp/myoutput.res
Now is Thu May 12 12:07:01 CEST 2016. myvar=hi man
Now is Thu May 12 12:08:01 CEST 2016. myvar=hi man
...
10
fedorqui

Au lieu de

0  *  *  *  *  sh /my/script.sh

Utilisez bash -l -c

0  *  *  *  *  bash -l -c 'sh /my/script.sh'
6
Ilya Kharlamov

Développer @Robert Brisita vient de se développer. Si vous ne souhaitez pas configurer toutes les variables du profil dans le script, vous pouvez sélectionner les variables à exporter en haut du script.

Dans le fichier crontab -e:

Shell=/bin/bash

*/1 * * * * /Path/to/script/script.sh

Dans script.sh

#!/bin/bash
export Java_HOME=/path/to/jdk

some-other-command
4
Marcos Pousada

Une autre manière - inspirée par ceci cette réponse - d’injecter des variables est la suivante (exemple fcron):

%daily 00 12 \
    set -a; \
    . /path/to/file/containing/vars; \
    set +a; \
    /path/to/script/using/vars

De help set:

-a Marque les variables qui sont modifiées ou créées pour l'exportation.

L'utilisation de + plutôt que de - désactive ces indicateurs.

Ainsi, tout ce qui se trouve entre set - et set + est exporté vers env et est ensuite disponible pour d'autres scripts, etc. Sans utiliser set, les variables sont recherchées mais résident dans set seulement.

En dehors de cela, il est également utile de passer des variables lorsqu'un programme nécessite l'exécution d'un compte non-root mais que vous avez besoin de certaines variables dans l'environnement de cet autre utilisateur. Voici un exemple en passant à nullmailer vars pour formater l'en-tête de courrier électronique:

su -s /bin/bash -c "set -a; \
                    . /path/to/nullmailer-vars; \
                    set +a; \
                    /usr/sbin/logcheck" logcheck
2
Saucier

J'ai essayé la plupart des solutions fournies, mais rien n'a fonctionné au début. Il s'avère toutefois que ce ne sont pas les solutions qui ont échoué. Apparemment, mon fichier ~/.bashrc commence par le bloc de code suivant:

case $- in
    *i*) ;;
    *) return;;
esac

Il s'agit essentiellement d'un case statement qui vérifie le jeu d'options actuel dans le shell actuel pour déterminer que celui-ci s'exécute de manière interactive. Si le shell s'exécute de manière interactive, il passe ensuite à la recherche du fichier ~/.bashrc. Cependant, dans un Shell appelé par cron, la variable $- ne contient pas la valeur i qui indique une interactivité. Par conséquent, le fichier ~/.bashrc ne sera jamais entièrement source. En conséquence, les variables d'environnement ne sont jamais définies. Si cela vous pose problème, n'hésitez pas à commenter le bloc de code comme suit et essayez à nouveau:

# case $- in
#     *i*) ;;
#     *) return;;
# esac

J'espère que cela s'avère utile

2
Abdou

J'utilise Oh-my-zsh dans mon macbook. J'ai donc essayé beaucoup de choses pour que la tâche crontab s'exécute, mais finalement, ma solution préfigurait le .zshrc avant l'exécution de la commande.

*/30 * * * * . $HOME/.zshrc; node /path/for/my_script.js

Cette tâche s'exécute toutes les 30 minutes et utilise le profil .zshrc pour exécuter ma commande de nœud.

N'oubliez pas d'utiliser le point avant le $HOME var.

1
Alekosdat