Где установлен cron PATH?

34

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

Я создал crontab со следующим содержимым в моей системе Arch (cronie 1.5.1-1), а также протестировал на Ubuntu 16.04.3 LTS box с такими же результатами:

$ 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ō
@ SatōKatsura, конечно, я упоминал только /etc/profileпотому, что он использует тот же синтаксис ( var=value), что и cronсам, так что это будет достаточно легко сделать, и /etc/profile, насколько мне известно, очень широко распространен. Что меня удивило, так это то, что я не мог найти его где-то установленным, так что это выглядело жестко. Как на самом деле, как объяснил Стивен ниже.
Terdon
Людям, использующим в zshкачестве своей интерактивной оболочки, плевать на то /etc/profile(что характерно для них bash)
Старынкевич,
2
@BasileStarynkevitch нет, это не относится к Баш на всех ! Наоборот! Хотя есть некоторые оболочки, которые не читают его (семейство c-shell AFAIK), zsh не является одним из них. Смотрите man-страницу zsh, если вы мне не верите. В любом случае, интерактивные оболочки не имеют значения, поскольку различные profileфайлы в любом случае читаются только оболочками входа в систему. Они могут или не могут быть интерактивными.
Тердон
1
Иногда запуск stringsпрограммы также может помочь найти эти жестко запрограммированные значения.
jrw32982 поддерживает Monica

Ответы:

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 echo $PATH > /testfile) после редактирования crontab root с использованием crontab -eв Debian Stretch, который также использует crontab root _PATH_DEFPATH, то есть «/ usr / bin: / bin», а не _PATH_DEFPATH_ROOT . Это также подтверждается второй ссылкой исходного кода в этом ответе (в которой _PATH_DEFPATH_ROOTне используется). Мне не ясно, является ли это осиротевшее определение ошибкой.
njahnke
8

В добавление к ответу Стивена Китта, есть файл конфигурации, который задает PATHдля cron в Ubuntu и cron игнорирует его , PATHчтобы использовать жестко PATHзаданное значение по умолчанию (или s, заданное в самих 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/foocronjob и наблюдайте, как 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задание, вы увидите, что оно явно настраивает среду так, чтобы она соответствовала среде, в которой оно было создано.
Стивен Китт