Cron n'utilise pas le chemin de l'utilisateur dont il est le crontab et, à la place, a le sien. Il peut facilement être modifié en ajoutant PATH=/foo/bar
au début de la crontab, et la solution de contournement classique consiste à toujours utiliser des chemins absolus vers les commandes exécutées par cron, mais où le PATH par défaut de cron est-il défini?
J'ai créé une crontab avec le contenu suivant sur mon système Arch (cronie 1.5.1-1) et j'ai également testé sur une boîte Ubuntu 16.04.3 LTS avec les mêmes résultats:
$ crontab -l
* * * * * echo "$PATH" > /home/terdon/fff
Cela a imprimé:
$ cat fff
/usr/bin:/bin
Mais pourquoi? Le chemin d'accès par défaut à l'échelle du système est défini dans /etc/profile
, mais cela inclut d'autres répertoires:
$ grep PATH= /etc/profile
PATH="/usr/local/sbin:/usr/local/bin:/usr/bin"
Il n'y a rien d'autre de pertinent dans /etc/environment
ou /etc/profile.d
, les autres fichiers que je pensais pourraient être lus par cron:
$ grep PATH= /etc/profile.d/* /etc/environment
/etc/profile.d/jre.sh:export PATH=${PATH}:/usr/lib/jvm/default/bin
/etc/profile.d/mozilla-common.sh:export MOZ_PLUGIN_PATH="/usr/lib/mozilla/plugins"
/etc/profile.d/perlbin.sh:[ -d /usr/bin/site_Perl ] && PATH=$PATH:/usr/bin/site_Perl
/etc/profile.d/perlbin.sh:[ -d /usr/lib/Perl5/site_Perl/bin ] && PATH=$PATH:/usr/lib/Perl5/site_Perl/bin
/etc/profile.d/perlbin.sh:[ -d /usr/bin/vendor_Perl ] && PATH=$PATH:/usr/bin/vendor_Perl
/etc/profile.d/perlbin.sh:[ -d /usr/lib/Perl5/vendor_Perl/bin ] && PATH=$PATH:/usr/lib/Perl5/vendor_Perl/bin
/etc/profile.d/perlbin.sh:[ -d /usr/bin/core_Perl ] && PATH=$PATH:/usr/bin/core_Perl
Il n'y a également rien de pertinent dans aucun des fichiers de /etc/skel
, sans surprise, ni défini dans aucun /etc/cron*
fichier:
$ grep PATH /etc/cron* /etc/cron*/*
grep: /etc/cron.d: Is a directory
grep: /etc/cron.daily: Is a directory
grep: /etc/cron.hourly: Is a directory
grep: /etc/cron.monthly: Is a directory
grep: /etc/cron.weekly: Is a directory
/etc/cron.d/0hourly:PATH=/sbin:/bin:/usr/sbin:/usr/bin
Alors, où le PATH par défaut de cron pour les crontabs utilisateur est-il défini? Est-il codé en dur dans cron
lui-même? Ne lit-il pas une sorte de fichier de configuration pour cela?
Il est codé en dur dans le code source (ce lien pointe vers la version actuelle de Debian cron
- étant donné la variété des implémentations de cron
, il est difficile d'en choisir une, mais d'autres les implémentations sont probablement similaires):
#ifndef _PATH_DEFPATH
# define _PATH_DEFPATH "/usr/bin:/bin"
#endif
cron
ne lit pas les chemins par défaut d'un fichier de configuration; J'imagine que le raisonnement est qu'il prend en charge la spécification de chemins utilisant déjà PATH=
dans n'importe quel cronjob, il n'est donc pas nécessaire de pouvoir spécifier une valeur par défaut ailleurs. (La valeur par défaut codée en dur est utilisée si rien d'autre ne spécifie un chemin dans une entrée de travail .)
Ajoutant à la réponse de Stephen Kitt, il existe un fichier de configuration qui définit PATH
pour cron sur Ubuntu, et cron
ignore que PATH
pour utiliser la valeur par défaut codée en dur (ou PATH
s définie dans les crontabs elles-mêmes). Le fichier est /etc/environment
. Remarque la configuration PAM de cron
:
$ cat /etc/pam.d/cron
...
# Read environment variables from pam_env's default files, /etc/environment
# and /etc/security/pam_env.conf.
session required pam_env.so
# In addition, read system locale information
session required pam_env.so envfile=/etc/default/locale
...
Ceci est facilement vérifiable. Ajoutez une variable à /etc/environment
, dire foo=bar
, courir env > /tmp/foo
comme un cronjob et regardez comme foo=bar
apparaît dans la sortie.
Mais pourquoi? Le chemin par défaut à l'échelle du système est défini dans/etc/profile, mais cela inclut d'autres répertoires:
$ grep PATH= /etc/profile PATH="/usr/local/sbin:/usr/local/bin:/usr/bin"
C'est vrai dans Arch Linux, mais dans Ubuntu, la base PATH
est définie dans /etc/environment
. Fichiers dans /etc/profile.d
virer à un PATH
existant, et vous pouvez l'ajouter dans ~/.pam_environment
. J'ai n bug a été déposé sur le comportement d'Arch .
Malheureusement, /etc/pam.d/cron
n'inclut pas la lecture de ~/.pam_environment
. Bizarrement, /etc/pam.d/atd
inclut ce fichier:
$ cat /etc/pam.d/atd
#
# The PAM configuration file for the at daemon
#
@include common-auth
@include common-account
session required pam_loginuid.so
@include common-session-noninteractive
session required pam_limits.so
session required pam_env.so user_readenv=1
... mais les commandes exécutées via at
héritent apparemment de l'environnement disponible lors de la création du travail at
(par exemple, env -i /usr/bin/at ...
semble exécuter des travaux dans un environnement très propre).
Modification /etc/pam.d/cron
avoir user_readenv=1
semble ne causer aucun problème, et les variables dans ~/.pam_environment
a commencé à apparaître correctement (sauf pour PATH
, bien sûr).
Tout compte fait, la définition de variables d'environnement pour cron semble être une entreprise compliquée. Le meilleur endroit semble être dans la spécification du travail elle-même, ne serait-ce que parce que vous ne savez pas quelles variables d'environnement héritées cron pourrait décider d'ignorer (sans lire la source).