Де встановлено PATH Cron?


34

Cron не використовує шлях того користувача, у якого він є, а натомість має свій власний. Це можна легко змінити, додавши PATH=/foo/barна початку crontab, і класичним способом вирішення є завжди використовувати абсолютні шляхи до команд, керованих cron, але де визначено PATH за замовчуванням Cron?

Я створив crontab із наступним вмістом у своїй системі Arch (cronie 1.5.1-1), а також протестував на коробці Ubuntu 16.04.3 LTS з тими ж результатами:

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

Надруковано:

$ cat fff
/usr/bin:/bin

Але чому? Встановлено стандартний шлях за загальною системою /etc/profile, але він включає інші каталоги:

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

Немає нічого іншого, що стосується /etc/environmentабо /etc/profile.d, інших файлів, які я вважав, можливо, можуть прочитати 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

Немає нічого релевантного в жодному з файлів у /etc/skel, не дивно, і він не встановлений у жодному /etc/cron*файлі:

$ 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

Отже, де встановлюється PATH за замовчуванням Cron для користувачів crontabs? Це твердо кодоване cronсаме по собі? Чи не читає якийсь файл конфігурації для цього?


3
Немає підстав cronдивитись /etc/profileабо піклуватися про якусь конкретну оболонку. Краще питання, чому він не cronчитає PATHз login.defs(на Linux) або login.conf(на * BSD). Я вважаю, що це в кінцевому підсумку деталі реалізації.
Satō Katsura

@ SatōKatsura впевнений, я лише згадав, /etc/profileоскільки він використовує той самий синтаксис ( var=value), що і cronсам, тому це зробити досить легко і /etc/profile, наскільки мені відомо, дуже поширений. Що мене здивувало, це те, що я не міг знайти його встановити ніде, так що це виглядало так, як це було важко закодовано. Як це справді так, як пояснив Стівен нижче.
тердон

Люди, які використовують zshсвою інтерактивну оболонку, не переймаються /etc/profile(що характерно для bash)
Basile Starynkevitch

2
@BasileStarynkevitch немає, це не відноситься до Баш на всіх ! Зовсім навпаки! Хоча є кілька оболонок, які не читають його (сім'я c-shell AFAIK), zsh не є однією з них. Дивіться zsh manpage, якщо ви мені не вірите. У будь-якому випадку, інтерактивні оболонки не мають значення, оскільки різні profileфайли в будь-якому разі читаються лише оболонками для входу. Вони можуть бути або не бути інтерактивними.
тердон

1
Іноді біг stringsпроти програми також може допомогти знайти ці важко кодовані значення.
jrw32982 підтримує Моніку

Відповіді:


47

Це важко закодовано у вихідному коді (це посилання вказує на поточний Debian cron- враховуючи різноманітність cronреалізацій, важко вибрати одну, але інші реалізації, ймовірно, схожі):

#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

cronне читає шляхи за замовчуванням з файлу конфігурації; Я думаю, що міркування полягають у тому, що він підтримує вказівку шляхів, які вже використовуються PATH=в будь-якій cronjob, тому не потрібно вказувати дефолт в іншому місці. (Жорстко закодований за замовчуванням використовується, якщо нічого іншого не вказав шлях у записі завдання .)


Зауважте, що, незважаючи на існування _PATH_DEFPATH_ROOTвизначення, я підтвердив (використовуючи завдання cron of echo $PATH > /testfile) після редагування crontab root crontab -eна Debian Stretch, що також використовується crontab кореня _PATH_DEFPATH, тобто "/ usr / bin: / bin", ні _PATH_DEFPATH_ROOT . Це також підтверджується другим посиланням на вихідний код у цій відповіді (в якому _PATH_DEFPATH_ROOTвін не використовується). Мені незрозуміло, чи є це дефіцит сиріт помилкою.
njahnke

8

Додаючи до відповіді Стівена Кітта, є файл конфігурації, який встановлює PATHcron на Ubuntu, і cron ігнорує його PATHдля використання жорстко закодованого за замовчуванням (або PATHs, встановленого в самих crontabs). Файл є /etc/environment. Прим cron«сек конфігурації 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
...

Це легко перевірити. Додайте змінну /etc/environment, скажімо foo=bar, запускайте env > /tmp/fooяк cronjob і дивіться, як foo=barвідображається у висновку.


Але чому? Шлях для всієї системи за замовчуванням встановлений у / etc / profile, але він включає інші каталоги:

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

Це вірно в Arch Linux, але в Ubuntu база PATHвстановлена /etc/environment. Файли /etc/profile.dвикористовуються для вже наявного PATH, і ви можете додати його в ~/.pam_environment. У мене є помилка щодо поведінки Арка .

На жаль, /etc/pam.d/cronне включає читання з ~/.pam_environment. Як не дивно, /etc/pam.d/atd чи включає цей файл:

$ 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

... але команди, що виконуються через, atочевидно, успадковують середовище, доступне під час створення atзавдання (наприклад, env -i /usr/bin/at ...здається, що вони виконують завдання з дуже чистим середовищем).

Зміна /etc/pam.d/cron, user_readenv=1мабуть, не викликає проблем, і змінні в ~/.pam_environmentпочатковому показі штрафу (за винятком PATH, звичайно,).


Все, що говорити, встановлення змінних середовища для cron здається безладним справою. Найкраще місце, здається, знаходиться в самій специфікації завдання, хоча б тому, що ви не знаєте, які успадковані змінні середовища cron можуть вирішити ігнорувати (не читаючи джерело).


Що стосується atзавдань, якщо ви скидаєте atроботу, ви побачите, що вона явно задає середовище відповідно до середовища, коли завдання було створено.
Стівен Кітт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.