web-dev-qa-db-fra.com

Comment puis-je exécuter une commande cron avec des variables d'environnement existantes?

Comment puis-je exécuter une commande cron avec des variables d'environnement existantes?

Si je suis à une invite Shell, je peux taper echo $Oracle_HOME et obtenez un chemin. Ceci est l'une de mes variables environnementales qui est définie dans mon ~/.profile. Cependant, il semble que ~/.profile ne reçoit pas de scripts cron chargés et donc mes scripts échouent parce que $Oracle_HOME la variable n'est pas définie.

Dans cette question l'auteur mentionne la création d'un ~/.cronfile profil qui définit des variables pour cron, puis il fait une solution de contournement pour charger toutes ses commandes cron dans des scripts qu'il conserve dans son ~/Cron répertoire. Un fichier comme ~/.cronfile semble être une bonne idée, mais le reste de la réponse semble un peu lourd et j'espérais que quelqu'un pourrait me dire un moyen plus simple d'obtenir le même résultat.

Je suppose qu'au début de mes scripts, je pourrais ajouter quelque chose comme source ~/.profile mais cela semble être redondant.

Alors, comment puis-je faire en sorte que mes scripts cron chargent les variables de mon profil shell interactif?

126
cwd

Dans la crontab, avant de commander, ajoutez . $HOME/.profile. Par exemple:

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

Cron ne sait rien de votre Shell; il est démarré par le système, il a donc un environnement minimal. Si vous voulez quelque chose, vous devez le faire vous-même.

154
Arcege

Une autre option, que je trouve plus facile, est d'exécuter le script avec cron et d'avoir 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é.

45
Robert Brisita

Une autre option, que je trouve plus facile, est d'exécuter le script avec cron et de dire à bash de se connecter (d'où l'utilisation de /etc/profile.d/... définitions d'environnement)

Dans crontab -e fichier:

*/1 * * * * bash -l -c './cron_job.sh'
*/1 * * * * bash -l -c 'php -f ./cron_job.php'

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

24
Artistan

Mauvaise idée. La pratique générale consiste à définir spécifiquement toutes les variables d'environnement requises dans un script qui doit être exécuté à partir d'un travail cron.

10
fpmurphy

Cette syntaxe vous aide certainement. Je ne comprends pas la syntaxe, mais ça marche. Oracle utilise cette syntaxe, lors du déploiement d'Oracle Configuration Manager pour crontab, donc, je pense que c'est une bonne solution.

0 5 * * * SOME_ENV_VAR=some_value some_command some_parameters
6
meir

Vous pouvez placer des variables d'environnement globales dans /etc/environment. Ils sont chargés lorsqu'un programme est exécuté par la crontab. Ex:

env | grep Oracle_HOME >> /etc/environment
service crontab restart

L'inconvénient est qu'il n'est pas limité à un seul utilisateur. Testé sous CentOS7

3
Kiruahxh

J'ai récemment rencontré un cas où je devais exécuter le cronjob global en tant que root mais, en même temps, je devais exécuter une sous-commande en tant qu'utilisateur différent (ce qui nécessitait de se procurer l'environnement de cet utilisateur). Je suis allé avec l'approche suivante:

# m  h  dom  mon  dow  user  command
*/5  *   *    *    *   root  (Sudo -i -u <the user> command-to-be-run-as-user) && command-to-be-run-as-root

La partie cruciale est l'argument -i qui est passé à Sudo qui exécutera la commande donnée dans un shell de connexion séparé (ce qui signifie que les fichiers de points de l'utilisateur seront fournis).

PS: notez que la colonne user n'est disponible qu'en /etc/crontab et le /etc/cron.d/* des dossiers.

2
balu

Oui, vous pouvez utiliser des "solutions de contournement bien connues" (dont deux ont été répertoriées). C'est une autre façon de dire que tout le monde sait que c'est merdique, bien que certaines personnes y feront référence comme une "fonction de sécurité" parce qu'elles ont dépensé au moins autant de trébuchements sur cet échec (ure) que vous, et aimeraient penser que leur le temps perdu n'était pas pour rien. C'est l'équivalent cron du clavier QWERTY.

Je soupçonne que la raison d'origine était peut-être la performance, de sorte que les scripts exécutés une fois par minute ne passeraient pas le temps de lire les scripts rc. Également à l'origine, cron n'était pas vraiment configurable du tout, donc une valeur par défaut était vraiment la seule option.

Il n'y a pas de sécurité supplémentaire en n'ayant pas de configuration ou de méthode simple pour que cron prenne simplement l'environnement de votre Shell interactif au lieu que les utilisateurs n'aient à effectuer une gymnastique de Shell stupide. Sur une machine moderne, il n'y a généralement pas de gain de performances perceptible, sauf si vous avez une grande quantité de travaux en cours d'exécution chaque minute.

La culture Unix échoue. À mon humble avis. :-)

1
Austin S.

Au lieu de définir le profil, ce qui m'a aidé était de définir le PATH. Certaines commandes n'étaient pas disponibles dans mes scripts cron car le PATH est différent.

ENVIRONMENT=prod
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
*/30 * * * * /opt/myscript1.sh
*/30 * * * * /opt/myscript2.sh
*/30 * * * * /opt/myscript3.sh

La définition de PATH avec le chemin des commandes m'a aidé. Encore mieux si vous pouvez utiliser un modèle et le démonter plus tard,

ENVIRONMENT={{ENVIRONMENT}}
PATH={{PATH}}
*/30 * * * * /opt/myscript1.sh
*/30 * * * * /opt/myscript2.sh
*/30 * * * * /opt/myscript3.sh

Passer des variables à chaque élément semble compliqué.

1
Optimus Prime

La solution, qui a fonctionné pour moi, est décrite ici .

Vous créez un script wrapper, qui appelle . ~/.cronfile, puis fait les choses que vous voulez. Ce script est lancé par cron.

Dans ~/.cronfile vous spécifiez l'environnement pour vos tâches cron.

1
weekens

Ajouter

BASH_ENV=/home/user/.profile

à la crontab. Voir Comment garantir la disponibilité de $ BASH_ENV

1
Enno