Gdzie jest ustawiona PATH crona?

34

Cron nie korzysta ze ścieżki użytkownika, którego crontab jest, a zamiast tego ma swoją własną. Można to łatwo zmienić, dodając PATH=/foo/barna początku crontab, a klasycznym obejściem jest zawsze używanie ścieżek bezwzględnych do poleceń uruchamianych przez crona, ale gdzie jest zdefiniowana domyślna ŚCIEŻKA crona?

Stworzyłem crontab z następującą zawartością w moim systemie Arch (cronie 1.5.1-1), a także testowałem na Ubuntu 16.04.3 LTS z tymi samymi wynikami:

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

Które wydrukowano:

$ cat fff
/usr/bin:/bin

Ale dlaczego? Domyślna ścieżka systemowa jest ustawiona /etc/profile, ale zawiera inne katalogi:

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

W innych plikach nie ma nic istotnego /etc/environmentlub /etc/profile.dcron:

$ 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

Tam też nic nie istotne w dowolne pliki /etc/skel, nie dziwi, ani nie jest to zestaw będąc w dowolnym /etc/cron*pliku:

$ 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

Więc gdzie jest ustawiona domyślna ŚCIEŻKA crona dla crontab użytkownika? Czy to jest zakodowane cronsamo w sobie? Czy nie czyta do tego jakiegoś pliku konfiguracyjnego?

terdon
źródło
3
Nie ma powodu, cronaby patrzeć /etc/profilelub dbać o jakąkolwiek konkretną powłokę. Lepszym pytaniem jest, dlaczego nie cronczyta PATHz login.defs(w systemie Linux) lub login.conf(w * BSD). Przypuszczam, że ostatecznie jest to szczegół implementacji.
Satō Katsura
@ SatōKatsura, oczywiście, wspomniałem tylko /etc/profiledlatego, że używa tej samej składni ( var=value) co cronsam, więc byłoby to łatwe do zrobienia i, o ile /etc/profilewiem, jest bardzo rozpowszechnione. Zaskoczyło mnie to, że nie mogłem go nigdzie ustawić, więc wyglądało na to, że jest mocno zakodowany. Tak jak w rzeczywistości, jak wyjaśnił Stephen poniżej.
terdon
Ludziom używającym zshjako interaktywnej powłoki nie obchodzi /etc/profile(co jest specyficzne bash)
Basile Starynkevitch
2
@BasileStarynkevitch nie, to nie jest specyficzne dla bash w ogóle ! Wręcz przeciwnie! Chociaż istnieją powłoki, które go nie czytają (AFAIK z rodziny c-shell), zsh nie jest jedną z nich. Zobacz stronę zsh, jeśli mi nie wierzysz. W każdym razie powłoki interaktywne nie mają znaczenia, ponieważ różne profilepliki są odczytywane tylko przez powłoki logowania. Mogą, ale nie muszą być interaktywne.
terdon
1
Czasami uruchamianie stringsz programem może również pomóc w znalezieniu tych zakodowanych wartości.
jrw32982 obsługuje Monikę

Odpowiedzi:

47

Jest na stałe zakodowany w kodzie źródłowym (ten link wskazuje na obecny Debian cron- biorąc pod uwagę różnorodność cronimplementacji, trudno jest wybrać jedną, ale inne implementacje są prawdopodobnie podobne):

#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

cronnie odczytuje domyślnych ścieżek z pliku konfiguracyjnego; Wyobrażam sobie, że istnieje uzasadnienie, że obsługuje ono określanie ścieżek, które już są używane PATH=w dowolnym kronice, więc nie ma potrzeby określania wartości domyślnej w innym miejscu. (Domyślne zakodowane jest używane, jeśli nic innego nie określa ścieżki we wpisie zadania ).

Stephen Kitt
źródło
Zauważ, że pomimo istnienia _PATH_DEFPATH_ROOTdefinicji, potwierdziłem (używając zadania cron echo $PATH > /testfile) po edycji crontab root'a używając crontab -eDebian Stretch, którego crontab root również używa _PATH_DEFPATH, tj. „/ Usr / bin: / bin”, a nie _PATH_DEFPATH_ROOT . Potwierdza to również drugi link kodu źródłowego w tej odpowiedzi (w którym _PATH_DEFPATH_ROOTnie jest używany). Nie jest dla mnie jasne, czy to osierocone określenie jest błędem.
njahnke
8

Dodając do odpowiedzi Stephena Kitta, istnieje plik konfiguracyjny, który ustawia PATHdla crona na Ubuntu i cron ignoruje to, PATHaby użyć zakodowanego domyślnego (lub PATHs ustawionego w samych plikach crontab). Plik jest /etc/environment. cronKonfiguracja PAM notatki :

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

Jest to łatwe do zweryfikowania. Dodaj zmienną do /etc/environment, powiedzmy foo=bar, uruchom env > /tmp/foojako cronjob i obserwuj, jak foo=barpokazuje wynik.


Ale dlaczego? Domyślna ścieżka systemowa jest ustawiona w / etc / profile, ale obejmuje inne katalogi:

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

To prawda w Arch Linux, ale w Ubuntu podstawa PATHjest ustawiona /etc/environment. Pliki dołączane do /etc/profile.distniejącego PATHi można do niego dołączyć ~/.pam_environment. Mam zgłoszony błąd dotyczący zachowania Archa .

Niestety /etc/pam.d/cronnie obejmuje czytania z ~/.pam_environment. Dziwnie, /etc/pam.d/atd nie należą do tego pliku:

$ 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

... ale polecenia uruchamiane przez atnajwyraźniej dziedziczą środowisko dostępne podczas tworzenia atzadania (na przykład env -i /usr/bin/at ...wydaje się uruchamiać zadania w bardzo czystym środowisku).

Zmieniająca /etc/pam.d/cronmieć user_readenv=1wydaje się powodować żadnych problemów, a zmienne ~/.pam_environmentzaczęły pojawiać się grzywny (z wyjątkiem PATH, oczywiście).


Podsumowując, ustawianie zmiennych środowiskowych dla crona wydaje się być bałaganem. Najlepszym miejscem wydaje się być sama specyfikacja zadania, choćby dlatego, że nie wiesz, które odziedziczone zmienne środowiskowe cron może zdecydować zignorować (bez czytania źródła).

muru
źródło
Jeżeli chodzi o at zadania, jeśli zrzucisz atzadanie, zobaczysz, że jawnie ustawia środowisko tak, aby pasowało do środowiska, w którym zostało utworzone zadanie.
Stephen Kitt