cron的PATH设置在哪里?


34

Cron不会使用crontab而是拥有自己的crontab的用户的路径。可以通过PATH=/foo/bar在crontab的开头添加内容来轻松更改它,经典的解决方法是始终使用绝对路径访问cron运行的命令,但是cron的默认PATH在哪里定义?

我在Arch系统(cronie 1.5.1-1)上创建了具有以下内容的crontab,并在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

那么,在哪里为用户crontabs设置了cron的默认PATH?它cron本身是硬编码的吗?它不是为此读取某种配置文件吗?


3
没有理由cron去看/etc/profile或关心任何特定的外壳。一个更好的问题是为什么不从(在Linux上)或(在* BSD上)cron读取。我想这最终是实现细节。PATHlogin.defslogin.conf
桂桂聪(SatōKatsura)

@SatōKatsura当然,我只提到了/etc/profile它,因为它使用与自身相同的语法(var=valuecron,所以这样做很容易/etc/profile,据我所知,它非常普及。令我惊讶的是,我找不到它可以放置在任何地方,因此看起来好像是硬编码的。的确如此,正如斯蒂芬在下面解释的那样。
terdon

人们将zsh它们用作交互式外壳并不关心/etc/profile(特定于bash
Basile Starynkevitch

2
@BasileStarynkevitch不,它不是专门针对bash !恰恰相反!尽管有一些不读的shell(c-shell系列AFAIK),但是zsh并不是其中之一。如果您不相信我,请参见zsh联机帮助页。在任何情况下,交互式外壳程序都是无关紧要的,因为无论如何,各种profile文件只能由登录外壳程序读取。这些可能是互动的,也可能不是互动的。
terdon

1
有时strings针对程序运行也可以帮助找到这些硬编码的值。
jrw32982支持莫妮卡

Answers:


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定义,但我在Debian Stretch上使用根的crontab也使用echo $PATH > /testfile根目录的crontab进行编辑后,确认了(使用cron作业),即“ / usr / bin:/ bin”,不是。此答案中的第二个源代码链接也证实了这一点(未使用)。我不清楚这个孤立的定义是否是一个错误。crontab -e_PATH_DEFPATH_PATH_DEFPATH_ROOT _PATH_DEFPATH_ROOT
njahnke '18

8

除了斯蒂芬·基特(Stephen Kitt)的答案,还有一个配置文件可PATH在Ubuntu上设置cron,而cron 忽略该配置文件PATH以使用硬编码默认值(或PATHcrontabs本身中设置的s)。文件是/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=barenv > /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。我有一个关于Arch行为的bug

不幸的是,/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/cronuser_readenv=1似乎不会引起问题,变数~/.pam_environment开始出现精(除PATH,当然)。


总而言之,为cron设置环境变量似乎很麻烦。最好的地方似乎是作业规范本身,因为仅仅是因为您不知道cron可能决定忽略哪个继承的环境变量(无需阅读源代码)。


关于at作业,如果您转储at作业,您会看到它明确地将环境设置为与创建作业时的环境匹配。
史蒂芬·基特
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.