Wo ist crons PATH eingestellt?

34

Cron verwendet nicht den Pfad des Benutzers, dessen crontab es ist, und hat stattdessen einen eigenen. Es kann leicht geändert werden, indem PATH=/foo/baram Anfang der crontab hinzugefügt wird. Die klassische Problemumgehung besteht darin, immer absolute Pfade zu Befehlen zu verwenden, die von cron ausgeführt werden. Aber wo ist crons Standard-PATH definiert?

Ich habe eine Crontab mit den folgenden Inhalten auf meinem Arch-System (cronie 1.5.1-1) erstellt und auch auf einer Ubuntu 16.04.3 LTS-Box mit den gleichen Ergebnissen getestet:

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

Das gedruckt:

$ cat fff
/usr/bin:/bin

Aber wieso? Der systemweite Standardpfad ist in festgelegt /etc/profile, umfasst jedoch auch andere Verzeichnisse:

$ grep PATH= /etc/profile
PATH="/usr/local/sbin:/usr/local/bin:/usr/bin"

Es gibt nichts anderes Relevantes in /etc/environmentoder /etc/profile.din den anderen Dateien, von denen ich dachte, dass sie möglicherweise von cron gelesen werden:

$ 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

Es ist auch nicht /etc/skelüberraschend, dass keine der Dateien in relevant ist oder in einer /etc/cron*Datei gesetzt wird:

$ 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

Wo wird der Standard-Pfad von cron für Benutzer-Crontabs festgelegt? Ist es in sich cronselbst fest codiert ? Liest es dafür keine Konfigurationsdatei?

terdon
quelle
3
Es gibt keinen Grund , sich eine bestimmte Schale cronanzuschauen /etc/profileoder sich um sie zu kümmern . Eine bessere Frage ist, warum nicht von (unter Linux) oder (unter * BSD) crongelesen wird . Ich nehme an, es ist letztendlich ein Implementierungsdetail. PATHlogin.defslogin.conf
Satō Katsura
@ SatōKatsura sicher, ich habe nur erwähnt, /etc/profileweil es die gleiche Syntax ( var=value) wie sich cronselbst verwendet, es wäre also einfach genug und /etc/profileist meines Wissens sehr weit verbreitet. Was mich überrascht hat, ist, dass ich es nirgendwo finden konnte und es so aussah, als wäre es hart codiert. Wie es tatsächlich der Fall ist, wie Stephen weiter unten erklärte.
Terdon
Menschen, die zshals interaktive Shell verwenden, interessieren sich nicht /etc/profile(was spezifisch für bash)
Basile Starynkevitch
2
@BasileStarynkevitch nein, es ist nicht spezifisch für bash überhaupt ! Ganz im Gegenteil! Während es einige Shells gibt, die es nicht lesen (die C-Shell-Familie AFAIK), gehört zsh nicht dazu. Schauen Sie sich die zsh-Manpage an, wenn Sie mir nicht glauben. In jedem Fall sind interaktive Shells irrelevant, da die verschiedenen profileDateien ohnehin nur von Login-Shells gelesen werden. Diese können interaktiv sein oder auch nicht.
Terdon
1
Manchmal stringskann es auch hilfreich sein, ein Programm zu verwenden, um diese fest codierten Werte zu finden.
jrw32982 unterstützt Monica

Antworten:

47

Es ist im Quellcode fest codiert (dieser Link verweist auf das aktuelle Debian cron- angesichts der Vielzahl von cronImplementierungen ist es schwierig, eine auszuwählen, andere Implementierungen sind jedoch wahrscheinlich ähnlich):

#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

cronliest keine Standardpfade aus einer Konfigurationsdatei; Ich stelle mir vor, dass es die Angabe von Pfaden unterstützt, die bereits PATH=in einem Cronjob verwendet werden, sodass es nicht erforderlich ist, an anderer Stelle einen Standardwert anzugeben. (Die fest codierte Standardeinstellung wird verwendet, wenn in einem Auftragseintrag kein anderer Pfad angegeben wurde .)

Stephen Kitt
quelle
Beachten Sie, dass _PATH_DEFPATH_ROOTich trotz des Vorhandenseins des Defines (unter Verwendung eines Cron-Jobs von echo $PATH > /testfile) bestätigt habe, nachdem ich die crontab des Roots unter Verwendung crontab -evon Debian Stretch bearbeitet habe, die auch die crontab des Roots verwendet _PATH_DEFPATH, dh "/ usr / bin: / bin", nicht _PATH_DEFPATH_ROOT . Dies wird auch durch den zweiten Quellcode-Link in dieser Antwort bestätigt (in der _PATH_DEFPATH_ROOTnicht verwendet wird). Mir ist nicht klar, ob diese verwaiste Definition ein Fehler ist.
Njahnke
8

Stephen Kitts Antwort wird durch eine Konfigurationsdatei ergänzt, die PATHunter Ubuntu für cron festgelegt wird und diese cron ignoriert , PATHum die fest codierten Standardeinstellungen (oder PATHdie in den Crontabs selbst festgelegten Werte) zu verwenden. Die Datei ist /etc/environment. Beachten Sie crondie PAM-Konfiguration:

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

Dies ist leicht überprüfbar. Fügen Sie eine Variable zu /etc/environment, sagen wir foo=bar, laufen env > /tmp/fooals cronjob und zusehen , wie foo=barShows in der Ausgabe auf.


Aber wieso? Der systemweite Standardpfad ist in / etc / profile festgelegt, umfasst jedoch auch andere Verzeichnisse:

$ grep PATH= /etc/profile
PATH="/usr/local/sbin:/usr/local/bin:/usr/bin"

Das stimmt in Arch Linux, aber in Ubuntu ist die Basis PATHgesetzt /etc/environment. Dateien werden /etc/profile.dan eine vorhandene PATHangefügt, und Sie können sie in anhängen ~/.pam_environment. Ich habe einen Fehler bezüglich Archs Verhalten .

Leider /etc/pam.d/cronschließt das Lesen nicht aus ~/.pam_environment. Seltsam, /etc/pam.d/atd hat diese Datei enthält:

$ 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

... aber Befehle, die über ausgeführt werden at, erben anscheinend die Umgebung, die beim Erstellen des atJobs verfügbar ist (zum Beispiel env -i /usr/bin/at ...scheinen Jobs mit einer sehr sauberen Umgebung ausgeführt zu werden).

Die Änderung /etc/pam.d/cronvon have user_readenv=1scheint keine Probleme zu bereiten, und die Variablen in sind ~/.pam_environmentin Ordnung (außer PATHnatürlich).


Alles in allem scheint das Festlegen von Umgebungsvariablen für cron ein chaotisches Geschäft zu sein. Der beste Platz scheint in der Auftragsspezifikation selbst zu sein, schon allein deshalb, weil Sie nicht wissen, welche vererbten Umgebungsvariablen cron möglicherweise ignoriert (ohne die Quelle zu lesen).

muru
quelle
In Bezug auf atArbeitsplätze, wenn Sie einen Dump atJob Sie werden sehen , es ausdrücklich die Umwelt richtet die Umgebung anzupassen , wenn der Auftrag erstellt wurde.
Stephen Kitt