关于linux:我在哪里可以设置crontab将使用的环境变量?

Where can I set environment variables that crontab will use?

我每小时都要运行一个crontab。运行它的用户在.bash_profile中有环境变量,当用户从终端运行作业时,这些变量会起作用,但是,很明显,在运行时,crontab不会接收到这些变量。

我试过把它们放在.profile.bashrc中,但它们似乎还没有被发现。有人知道我可以在哪里放置crontab可以收集的环境变量吗?


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

1
2
3
4
5
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)中声明这些内容。

archlinux和redhat使用cronie,它不允许声明环境变量,并将在cron.log中引发语法错误。每个条目都可以进行解决方法:

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


我还有一个解决这个问题的方法:

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

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

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


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

总是。

1
2
3
4
5
6
7
8
9
10
#   @(#)$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"的链接,它看起来像:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
:      "$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等。(真正的居家用品是我的环境的假象-你可以假装它和$home一样。)

因此,此代码读取适当的环境,然后从我的主目录执行命令的非cron版本。例如,我的"weekday"命令如下:

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

# Update ICSCOPE
n.updics

"daily"命令更简单:

1
2
3
4
5
6
7
:      "@(#)$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

/etc/environment中设置vars也在Ubuntu为我工作。截至12.04,/etc/environment中的变量是为cron加载的。


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

在crontab-e文件中:

1
2
3
SHELL=/bin/bash

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

在cron_job.sh文件中:

1
2
3
#!/bin/bash
source $HOME/.bash_profile
some_other_cmd

.bash_profile源之后的任何命令都会让您的环境看起来像是登录的一样。


如果通过cron启动正在执行的脚本,则使用:

1
#!/bin/bash -l

他们应该收集你的~/.bash_profile环境变量


对于我来说,我必须为一个PHP应用程序设置环境变量。我通过在crontab中添加以下代码来重新编写它。

1
$ sudo  crontab -e

crontab:

1
2
3
ENVIRONMENT_VAR=production

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

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

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

希望这有帮助!


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

在cronjob的定义中使用它们

您可以配置crontab,以便它设置变量,然后cronjob可以使用:

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

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

1
2
3
$ 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,以便它设置变量,然后脚本可以使用:

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

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

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

它生成一个文件/tmp/myoutput.res,显示:

1
2
3
4
$ 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
...

而不是

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

使用BASH-L-C

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


在@robert brisita上展开刚刚展开,如果不想在脚本中设置配置文件的所有变量,也可以选择要在脚本顶部导出的变量。

在crontab-e文件中:

1
2
3
SHELL=/bin/bash

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

在脚本中

1
2
3
4
#!/bin/bash
export JAVA_HOME=/path/to/jdk

some-other-command

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

1
2
3
4
case $- in
    *i*) ;;
    *) return;;
esac

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

1
2
3
4
# case $- in
#     *i*) ;;
#     *) return;;
# esac

我希望这个有用


另一种方法(受此答案启发)"inject"变量如下(fcron示例):

1
2
3
4
5
%daily 00 12 \
    set -a; \
    . /path/to/file/containing/vars; \
    set +a; \
    /path/to/script/using/vars

来自help set

-a Mark variables which are modified or created for export.

Using + rather than - causes these flags to be turned off.

因此,set -set +之间的所有内容都被导出到env中,然后可用于其他脚本等,而不使用set,变量只在set中获得源,但只在set中存在。

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

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