Où se trouve le PATH de cron?

34

Cron n'utilise pas le chemin de l'utilisateur dont elle est la crontab et a le sien. Elle peut facilement être modifiée en ajoutant PATH=/foo/barau début de la crontab, et la solution classique consiste à toujours utiliser des chemins absolus pour les commandes exécutées par cron, mais où est défini le PATH par défaut de cron?

J'ai créé une crontab avec le contenu suivant sur mon système Arch (cronie 1.5.1-1) et également testé sur une boîte Ubuntu 16.04.3 LTS avec les mêmes résultats:

$ crontab -l
* * * * * echo "$PATH" > /home/terdon/fff

C'est imprimé:

$ cat fff
/usr/bin:/bin

Mais pourquoi? Le chemin par défaut 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/environmentni /etc/profile.dles autres fichiers que je pensais susceptibles d'ê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’ya rien de /etc/skelsurprenant non plus dans les /etc/cron*fichiers qui se trouvent dans aucun 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ù est le PATH par défaut de cron pour les crontabs utilisateur en cours de définition? Est-ce qu'il est codé en dur cron? Ne lit-il pas une sorte de fichier de configuration pour cela?

terdon
la source
3
Il n'y a aucune raison cronde regarder /etc/profileou de s'intéresser à une coquille particulière. Une meilleure question est pourquoi ne pas cronlire à PATHpartir de login.defs(sous Linux) ou login.conf(* sur BSD). Je suppose que c'est finalement un détail de mise en œuvre.
Satō Katsura
@ SatōKatsura, bien sûr, je l’ai seulement mentionné /etc/profilecar il utilise la même syntaxe ( var=value) que cronlui-même, il serait donc assez facile à faire et /etc/profileest, à ma connaissance, très répandu. Ce qui m'a surpris, c'est que je ne pouvais pas le trouver installé nulle part, donc il semblait que c'était codé en dur. Comme c'est en effet le cas, comme l'a expliqué Stephen ci-dessous.
terdon
Les utilisateurs zshde shell interactif ne s’intéressent pas à la question /etc/profile(ce qui est propre à bash)
Basile Starynkevitch,
2
@BasileStarynkevitch Non, ce n'est pas spécifique à bash du tout ! Bien au contraire! Bien qu'il y ait des obus qui ne le lisent pas (la famille c-shell autant que je sache), zsh n'en fait pas partie. Voir la page de manuel zsh, si vous ne me croyez pas. Dans tous les cas, les shells interactifs ne sont pas pertinents car les différents profilefichiers ne sont lus que par des shells de connexion. Ceux-ci peuvent ou non être interactifs.
terdon
1
Parfois, exécuter stringscontre un programme peut aussi aider à trouver ces valeurs codées en dur.
jrw32982 prend en charge Monica

Réponses:

47

C'est codé en dur dans le code source (ce lien pointe vers l'actuelle Debian cron- étant donné la diversité des cronimplémentations, il est difficile d'en choisir une, mais d'autres implémentations sont probablement similaires):

#ifndef _PATH_DEFPATH
# define _PATH_DEFPATH "/usr/bin:/bin"
#endif

#ifndef _PATH_DEFPATH_ROOT
# define _PATH_DEFPATH_ROOT "/usr/sbin:/usr/bin:/sbin:/bin"
#endif

cronne lit pas les chemins par défaut à partir d'un fichier de configuration; J'imagine que la raison en est qu'il prend en charge la spécification de chemins déjà utilisés PATH=dans n'importe quel travail cron, il n'est donc pas nécessaire de pouvoir spécifier un paramètre par défaut ailleurs. (La valeur par défaut codée en dur est utilisée si rien d'autre n'a spécifié un chemin d'accès dans une entrée de travail .)

Stephen Kitt
la source
Notez que, malgré l’existence de la _PATH_DEFPATH_ROOTdéfinition, j’ai confirmé (en utilisant une tâche cron de echo $PATH > /testfile) après avoir modifié la crontab de la racine en utilisant crontab -esur Debian Stretch que la crontab de cette racine utilise également _PATH_DEFPATH, c’est-à-dire "/ usr / bin: / bin" _PATH_DEFPATH_ROOT . Ceci est également confirmé par le deuxième lien de code source dans cette réponse (dans lequel _PATH_DEFPATH_ROOTn'est pas utilisé). Il n'est pas clair pour moi si cette définition orpheline est un bogue.
njahnke
8

Ajout à la réponse de Stephen Kitt, il y a un fichier de configuration qui définit PATHCron sur Ubuntu, et cron ignore que PATHd'utiliser la valeur par défaut codées en dur (ou PATHs définies dans les crontabs eux - mêmes). Le fichier est /etc/environment. Remarque sur cronla configuration de PAM:

$ 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 pour /etc/environment, par exemple foo=bar, exécuter en env > /tmp/footant que travail cron et regarder comme indiqué foo=bardans la sortie.


Mais pourquoi? Le chemin par défaut 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 PATHest définie /etc/environment. Les fichiers sont /etc/profile.dajoutés à un fichier existant PATHet vous pouvez les ajouter à ~/.pam_environment. J'ai un bug sur le comportement d'Arch .

Malheureusement, /etc/pam.d/cronne comprend pas la lecture de ~/.pam_environment. Bizarrement, /etc/pam.d/atd ne comprend 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 athéritent apparemment de l'environnement disponible lors de la création du attravail (par exemple, env -i /usr/bin/at ...semble exécuter des travaux avec un environnement très propre).

Modifier /etc/pam.d/cronpour avoir user_readenv=1semble ne poser aucun problème, et les variables ~/.pam_environmentcommencent à apparaître très bien (sauf pour PATH, bien sûr).


Tout compte fait, définir des variables d'environnement pour cron semble être une entreprise complexe. Le meilleur endroit semble être dans la spécification du travail lui-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 le code source).

muru
la source
En ce qui concerne les attravaux, si vous atvidez un travail, vous verrez qu'il configure explicitement l'environnement pour qu'il corresponde à l'environnement lors de la création du travail.
Stephen Kitt