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

我已经尝试过在.profile.bashrc中设置它们,但它们似乎仍然没有被拾取。有谁知道我可以将crontab可以接收的环境变量放在哪里?

#1 楼

在运行命令之前,让'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 
:       "@(#)$Id: weekday.sh,v 1.10 2007/09/17 02:42:03 jleffler Exp $"
#
#       Commands to be done each weekday

# Update ICSCOPE
n.updics
` 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: 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


“每日”命令更简单:

q4312078q

#2 楼

从命令行运行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)中声明它们。

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

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


评论


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

–扎克
13年5月5日在10:13

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

–布鲁诺·兰格(Bruno Lange)
2015年6月9日在13:24

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

– vutran
15年11月13日在8:10

如@bruno所说,cronie现在确实从crontab中复制了除少数几个环境变量外的所有变量。

–mtd
19年2月2日,18:41



@BrunoLange,请您分享您如何设置它们?

–Newskooler
19年2月13日在16:35

#3 楼

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

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


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

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

评论


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

–vladimir montealegre
2012年12月27日在21:30

直到我意识到我没有在$ HOME之前的那段时间,这对我没有用。那段时间到底是做什么的?

–flymike
2013年5月5日在16:48



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

–杰夫W
13年8月8日在21:55

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

– Vishal
13年3月22日在5:48

@Vishal实际上,它现在对我有用。我试图获取〜/ .bashrc的资源,结果发现我的.bashrc文件与cron作业有点冲突。如果我仅使用一行仅使用一个非常简单的.env_setup_rc文件:export MY_ENV_VAR = my_env_val,它实际上可以工作。看到我的帖子:stackoverflow.com/questions/15557777/…

– Peter Lee
13年3月22日在5:53



#4 楼

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

评论


最佳答案,只需执行env >> / etc / environment,现在CRON作业中就可以使用所有当前的env var。

–野蛮人
16 Mar 16 '16 at 12:39

这对我来说很棒。尤其是因为我遇到了Docker容器,因此我不太关心“系统范围”的含义。

–卢卡斯·波特斯基(Lucas Pottersky)
16年5月25日在13:31

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

– Fran Marzoa
16年8月17日在9:41

注意:env >> / etc / environment将在环境变量之一中出现哈希符号时失败。我最难对应用程序进行故障排除。原来是一个包含“#”的密码,该密码在该步骤被截断。

–asachet
19-09-18在10:38

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

–麦克·啮齿动物
19-10-17在12:23



#5 楼

如果您通过以下命令通过cron执行脚本,请执行以下操作:

#!/bin/bash -l


它们应该获取您的~/.bash_profile环境变量

评论


这个答案应该得到更多的认可,并且应该只是被选择的答案:非常简单而优雅,避免了无数次需要在系统中跳转的麻烦。

–Giacomo1968
18/12/14在4:42

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

– Seamus
1月29日23:54

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

–breizhmg
4月25日晚上8:17

@Jim参见此示例,经典可执行文件(chmod 777)使用#!/ bin / bash。这里的魔术是添加-l

– Peter Krauss
5月6日2:24

这个人的解释:-l使bash就像被作为登录shell调用一样(请参阅下面的INVOCATION)。

–炒锅
11月19日12:10

#6 楼

扩展@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源文件之后的任何命令都将具有您登录后的环境。

#7 楼

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

$ sudo  crontab -e



ENVIRONMENT_VAR=production

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


doSomethingWonderful.php我可以使用以下方法获取环境值:

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


我希望这会有所帮助!

评论


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

–豪猪
19年6月26日在10:56

#8 楼

您在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

< br并说脚本/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
...


#9 楼

在@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


#10 楼

代替

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


使用bash -l -c

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


评论


为什么这样做而不是仅在文件顶部使用Bash声明使-l像这样:#!/ bin / bash -l?这另一个答案是简单而优雅的。

–Giacomo1968
18/12/14在4:41

如果我需要运行Perl / python / ruby​​脚本而不是bash怎么办?我无法在Python脚本的顶部添加#!/ bin / bash -l。

–伊利亚·哈拉莫夫(Ilya Kharlamov)
18/12/14在14:58



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

–Giacomo1968
18/12/14在20:35

#11 楼

我在Macbook中使用Oh-my-zsh,所以我尝试了很多事情来使crontab任务运行,但最终,我的解决方案是在运行命令之前添加.zshrc

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


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

不要忘记在$HOME变量前使用点。

#12 楼

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

0 * * * *   env VARIABLE=VALUE /usr/bin/mycommand


#13 楼

受此答案启发,另一种“注入”变量的方法如下(fcron示例):
%daily 00 12 \
    set -a; \
    . /path/to/file/containing/vars; \
    set +a; \
    /path/to/script/using/vars

help set开始:

-标记已修改或
使用+而不是-导致这些标志被关闭。

因此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


#14 楼

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

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


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

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


我希望这对您有帮助

#15 楼

对我来说,我必须在NodeJS文件中指定路径。
 // did not work!!!!!
require('dotenv').config()
 

而不是
 // DID WORK!!
require('dotenv').config({ path: '/full/custom/path/to/your/.env' })
 


#16 楼

不幸的是,crontabs的环境变量范围非常有限,因此每次corntab运行时都需要导出它们。
下面的示例是一个简单的方法,假设您将env vars保存在一个名为env的文件中,然后:
* * * * * . ./env && /path/to_your/command
这部分. ./env将导出它们,然后在您命令的相同范围内使用它们

#17 楼


全局设置环境

 sudo sh -c "echo MY_GLOBAL_ENV_TO_MY_CURRENT_DIR=$(pwd)" >> /etc/environment"
 


添加计划作业以启动脚本

 crontab -e

  */5 * * * * sh -c "$MY_GLOBAL_ENV_TO_MY_CURRENT_DIR/start.sh"
 

=)

#18 楼

以上所有解决方案都可以正常工作。
当环境变量中有任何特殊字符时,它将产生问题。
我找到了解决方案:
eval $(printenv | awk -F= '{print "export " "\"""\"""=""\"""\"" }' >> /etc/profile)