web-dev-qa-db-fra.com

Où se trouve le PATH de cron?

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?

36
terdon

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 .)

48
Stephen Kitt

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 PATHs 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).

9
muru