在哪里可以设置crontab将使用的环境变量?


266

我的crontab每小时运行一次。.bash_profile当用户从终端运行作业时,运行它的用户在工作中具有环境变量,但是,显然,crontab在运行时不会被环境变量吸收。

我尝试过将它们放入.profile.bashrc但是它们似乎仍然没有被捡起。有谁知道我可以将crontab可以接收的环境变量放在哪里?

Answers:


88

在运行命令之前,让'cron'运行一个设置环境的shell脚本。

总是。

#   @(#)$Id: crontab,v 4.2 2007/09/17 02:41:00 jleffler Exp $
#   Crontab file for Home Directory for Jonathan Leffler (JL)
#-----------------------------------------------------------------------------
#Min     Hour    Day     Month   Weekday Command
#-----------------------------------------------------------------------------
0        *       *       *       *       /usr/bin/ksh /work1/jleffler/bin/Cron/hourly
1        1       *       *       *       /usr/bin/ksh /work1/jleffler/bin/Cron/daily
23       1       *       *       1-5     /usr/bin/ksh /work1/jleffler/bin/Cron/weekday
2        3       *       *       0       /usr/bin/ksh /work1/jleffler/bin/Cron/weekly
21       3       1       *       *       /usr/bin/ksh /work1/jleffler/bin/Cron/monthly

〜/ bin / Cron中的脚本都是指向单个脚本“ runcron”的链接,如下所示:

:       "$Id: runcron.sh,v 2.1 2001/02/27 00:53:22 jleffler Exp $"
#
#       Commands to be performed by Cron (no debugging options)

#       Set environment -- not done by cron (usually switches HOME)
. $HOME/.cronfile

base=`basename $0`
cmd=${REAL_HOME:-/real/home}/bin/$base

if [ ! -x $cmd ]
then cmd=${HOME}/bin/$base
fi

exec $cmd ${@:+"$@"}

(使用较旧的编码标准编写-如今,我一开始会使用shebang'#!'。)

“〜/ .cronfile”是我的个人资料上的一个变体,供cron使用-严格不交互式,并且为了嘈杂而没有回声。您可以安排执行.profile等。(REAL_HOME的东西是我所处环境的伪像-您可以假装它与$ HOME相同。)

因此,此代码读取适当的环境,然后从我的主目录执行命令的非Cron版本。因此,例如,我的“工作日”命令如下所示:

:       "@(#)$Id: weekday.sh,v 1.10 2007/09/17 02:42:03 jleffler Exp $"
#
#       Commands to be done each weekday

# Update ICSCOPE
n.updics

“每日”命令比较简单:

:       "@(#)$Id: daily.sh,v 1.5 1997/06/02 22:04:21 johnl Exp $"
#
#       Commands to be done daily

# Nothing -- most things are done on weekdays only

exit 0

246

crontab -e从命令行运行时,可以在crontab本身中定义环境变量。

LANG=nb_NO.UTF-8
LC_ALL=nb_NO.UTF-8
# m h  dom mon dow   command

* * * * * sleep 5s && echo "yo"

此功能仅对cron的某些实现可用。Ubuntu和Debian当前使用vixie-cron,它允许在crontab文件(也是GNU mcron)中声明它们。

ArchlinuxRedHat使用cronie不允许声明环境变量,并且会在cron.log中引发语法错误。解决方法可以按条目进行:

# m h  dom mon dow   command
* * * * * export LC_ALL=nb_NO.UTF-8; sleep 5s && echo "yo"

58
请注意,不能像在shell中那样使用变量替换,因此像PATH = / usr / local / bin:$ PATH这样的声明将按字面解释。
Zac

8
我能够在RedHat 4.4.7-3和cronie-1.4.4-15.el6.x86_64下的crontab自身中设置环境变量
Bruno Lange

7
如果仅在命令内使用变量,则实际上并不需要导出变量,只需在命令之前添加它们即可。“ * * * * *睡眠5秒钟; LC_ALL = nb_NO.UTF-8 echo $ LC_ALL”
vutran


您可以分享@BrunoLange,您如何设法设置它们?
Newskooler19年

145

对于这个问题,我还有一个解决方案:

0 5 * * * . $HOME/.profile; /path/to/command/to/run

在这种情况下,它将选择$HOME/.profile文件中定义的所有环境变量。

当然$HOME也没有设置,您必须用的完整路径替换它$HOME


经过很多努力寻找答案后,这对我有用,谢谢!
vladimir montealegre

5
直到我意识到我没有在$ HOME之前的那段时间之前,这对我没有用。确切地说,那个时期在做什么?
flymike

9
该时间段等效于“源”命令:tldp.org/LDP/abs/html/special-chars.html#DOTREF
Jeff W

@PeterLee提到的任何内容对您有用吗?我写这篇文章是因为上述解决方案对我而言无效。如果上述解决方案不起作用,我将必须进行一些研究以找出原因。;-)
Vishal

3
@Vishal实际上,它现在对我有用。我试图这样做source ~/.bashrc,结果证明我的.bashrc文件与cron作业有点冲突。如果我使用一个.env_setup_rc只有一行的非常简单的文件:export MY_ENV_VAR=my_env_val,它实际上可以工作。请参阅我的文章:stackoverflow.com/questions/15557777/...
李彼得

63

/etc/environment在Ubuntu中设置vars 也对我有用。从12.04开始,/etc/environment将为cron加载in 中的变量。


11
最佳答案,只需执行即可,env >> /etc/environment并且CRON作业中现在可以使用所有当前的环境变量。
Savageman

6
这对我来说很棒。特别是因为我遇到了Docker容器,所以我不太关心“系统范围”的含义。
卢卡斯·波特斯基

14
@Savageman就像用融合炸弹杀死苍蝇一样,意外行为的风险也很高。
Fran Marzoa '16

2
要小心:env >> /etc/environment如果环境变量之一中有哈希符号,则将失败。我最难对应用程序进行故障排除。原来是一个包含“#”的密码,该密码在该步骤被截断。
asac

3
这应该是选择的答案。我不知道为什么人们将其他答案或与env >> / etc / environment有关的东西变得复杂。如果您希望这些环境变量可以普遍使用,请稍等一下编辑/环境,我的实验似乎证实了/ etc / environment中环境变量的导出语句对crontab以及用户都可用。问题:再次根据我的实验:看来这些环境变量在crontab本身中并未扩展!...即它们仅在称为的脚本中扩展!
麦克啮齿动物

39

如果启动脚本,则使用以下命令通过cron执行:

#!/bin/bash -l

他们应该了解您的~/.bash_profile环境变量


4
这个答案应该得到更多的赞同,而应该只是选择的答案:非常简单而优雅,避免了无数次需要在系统中跳转的纠缠。
JakeGould

我喜欢这个答案+1。是否可以/在运行root的crontab时使用?/home/root我的系统上没有文件夹,因此我看不到它与rootcrontab 一起工作。有想法吗?
Seamus

在脚本本身中。然后您通常使用cron运行该程序。
breizhmg

@Jim参见此示例,经典可执行文件(chmod 777)使用#!/bin/bash。不可思议的是,添加-l
彼得·克劳斯

22

在我发现更简单的@carestad示例上进行扩展,是使用cron运行脚本并在脚本中包含环境。

在crontab -e文件中:

SHELL=/bin/bash

*/1 * * * * $HOME/cron_job.sh

在cron_job.sh文件中:

#!/bin/bash
source $HOME/.bash_profile
some_other_cmd

.bash_profile源之后的任何命令都将具有您的环境,就像您登录一样。


16

对我来说,我必须为php应用程序设置环境变量。我通过在我的crontab中添加以下代码来喜欢它。

$ sudo  crontab -e

crontab:

ENVIRONMENT_VAR=production

* * * * * /home/deploy/my_app/cron/cron.doSomethingWonderful.php

在doSomethingWonderful.php中,我可以通过以下方式获取环境值:

<?php     
echo $_SERVER['ENVIRONMENT_VAR']; # => "production"

我希望这有帮助!


这对我不起作用。在crontab内部调用的脚本中,环境变量不可用。
Nikhil

12

无论您设置什么crontab,都可以直接在cronjobs中使用脚本中的变量,也可以使用脚本中的变量。

在cronjob的定义中使用它们

您可以进行配置,crontab以便它设置可以cronjob使用的变量:

$ crontab -l
myvar="hi man"
* * * * * echo "$myvar. date is $(date)" >> /tmp/hello

现在该文件/tmp/hello显示如下内容:

$ cat /tmp/hello 
hi man. date is Thu May 12 12:10:01 CEST 2016
hi man. date is Thu May 12 12:11:01 CEST 2016

在cronjob运行的脚本中使用它们

您可以进行配置,crontab以便它设置脚本可以使用的变量:

$ crontab -l
myvar="hi man"
* * * * * /bin/bash /tmp/myscript.sh

并说脚本/tmp/myscript.sh是这样的:

echo "Now is $(date). myvar=$myvar" >> /tmp/myoutput.res

它生成一个/tmp/myoutput.res显示以下内容的文件:

$ cat /tmp/myoutput.res
Now is Thu May 12 12:07:01 CEST 2016. myvar=hi man
Now is Thu May 12 12:08:01 CEST 2016. myvar=hi man
...

7

在@Robert Brisita上扩展只是在扩展,如果您不想在脚本中设置配置文件的所有变量,则可以选择要导出的变量在脚本顶部

在crontab -e文件中:

SHELL=/bin/bash

*/1 * * * * /Path/to/script/script.sh

在script.sh中

#!/bin/bash
export JAVA_HOME=/path/to/jdk

some-other-command

7

代替

0  *  *  *  *  sh /my/script.sh

使用bash -l -c

0  *  *  *  *  bash -l -c 'sh /my/script.sh'

1
为什么这样做,而不是仅仅有在文件的顶部猛砸声明都将-l是这样的:#!/bin/bash -l这另一个答案是简单而优雅的。
JakeGould

1
如果我需要运行Perl / python / ruby​​脚本而不是bash怎么办?我不能在Python脚本的顶部添加#!/ bin / bash -l。
伊利亚·哈拉莫夫

“如果我需要运行perl / python / ruby​​脚本而不是bash怎么办?” 很公平。但是在我看来,您可以编写一个简单的Bash脚本包装程序,然后调用Python脚本。我对PHP脚本也做类似的事情。原因是进程锁定在Bash中是更好和可靠的,但是Bash脚本编写仍然令人头疼。因此,我用PHP编写了一些复杂的内容,然后让Bash处理其余的内容。
JakeGould

3

我用Oh-my-zsh我的macbook所以我尝试了很多事情,才能在crontab任务运行,但最后,我溶液前面加上.zshrc命令运行之前。

*/30 * * * * . $HOME/.zshrc; node /path/for/my_script.js

该任务每30分钟运行一次,并使用.zshrc配置文件执行我的node命令。

不要忘记在$HOMEvar 之前使用点。


2

受此答案启发,另一种“注入”变量的方法如下(fcron示例):

%daily 00 12 \
    set -a; \
    . /path/to/file/containing/vars; \
    set +a; \
    /path/to/script/using/vars

来自help set

-a标记为导出而修改或创建的变量。

使用+而不是-导致这些标志被关闭。

因此,介于set -和之间的所有内容都set +将导出到env,然后可用于其他脚本等。不使用set变量就可以获取源代码,但set只能存在。

除此之外,当程序需要运行非root帐户但您需要在其他用户环境中添加一些变量时,传递变量也很有用。下面是一个传递nullmailer var来格式化电子邮件头的示例:

su -s /bin/bash -c "set -a; \
                    . /path/to/nullmailer-vars; \
                    set +a; \
                    /usr/sbin/logcheck" logcheck

2

我尝试了提供的大多数解决方案,但一开始没有任何效果。但是事实证明,并非解决方案无法奏效。显然,我的~/.bashrc文件以以下代码块开头:

case $- in
    *i*) ;;
    *) return;;
esac

这基本上是一种case statement检查当前shell中的当前选项集以确定shell正在交互运行的功能。如果Shell碰巧正在以交互方式运行,那么它将继续寻找~/.bashrc文件。但是,在由调用的shell中cron$-变量不包含i表示交互性的值。因此,该~/.bashrc文件永远不会完全获得。结果,从未设置环境变量。如果这恰好是您的问题,请按照以下说明随意注释代码块,然后重试:

# case $- in
#     *i*) ;;
#     *) return;;
# esac

我希望这对您有用


0

您还可以在命令前添加env注入环境变量,如下所示:

0 * * * *   env VARIABLE=VALUE /usr/bin/mycommand
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.