【问题标题】:Where can I set environment variables that crontab will use?我在哪里可以设置 crontab 将使用的环境变量?
【发布时间】:2011-01-14 20:21:55
【问题描述】:

我每小时运行一个 crontab。运行它的用户在.bash_profile 中有环境变量,当用户从终端运行作业时,这些环境变量会起作用,但是,显然这些不会在运行时被 crontab 拾取。

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

【问题讨论】:

  • 如果我一直在 Mac 上使用 GNU coreutils,那就太烦人了!!!!!

标签: linux unix environment-variables crontab


【解决方案1】:

对我来说,我必须为 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 中调用的脚本中不可用。
  • crontab 不支持用户定义的变量。有点违反直觉,但是...
【解决方案2】:

我在查看与标题匹配的类似问题时发现了这个问题,但我被 systemd 或 docker 使用的环境文件语法卡住了:

FOO=bar
BAZ=qux

这不适用于 Vishal's excellent answer,因为它们不是 bash 脚本(请注意缺少 export)。
我使用的解决方案是在运行命令之前将每一行读入 xargs 并导出它们:

0 5 * * * export $(xargs < $HOME/.env); /path/to/command/to/run

【讨论】:

    【解决方案3】:

    什么对我有用(基于 debian):

    1. 创建一个包含所有需要的环境变量的文件:

      #!/bin/bash
      环境 | grep VAR1= > /etc/环境
      环境 | grep VAR2= >> /etc/environment
      环境 | grep VAR3= >> /etc/environment

    2. 然后通过在调用需要它的脚本之前调用 env 文件来构建 crontab 内容,因此启动 cron 服务

      (crontab -l ; echo '* * * * * . /etc/environment; /usr/local/bin/python /mycode.py >> /var/log/cron-1.log 2>&1') | crontab
      服务定时启动

    nb : 对于python用例,一定要调用整个python路径,否则可能会调用错误的python,产生无意义的语法错误

    【讨论】:

      【解决方案4】:

      以上所有解决方案都可以正常工作。

      当您的环境变量中有任何特殊字符时,它会产生问题。

      我找到了解决办法:

      eval $(printenv | awk -F= '{print "export " "\""$1"\"""=""\""$2"\"" }' &gt;&gt; /etc/profile)

      【讨论】:

        【解决方案5】:
        • 全局设置环境
        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"
        

        =)

        【讨论】:

          【解决方案6】:

          不幸的是,crontab 的环境变量范围非常有限,因此您需要在每次运行corntab 时导出它们。

          一个简单的方法是下面的例子,假设你的环境变量在一个名为 env 的文件中,那么:

          * * * * * . ./env &amp;&amp; /path/to_your/command

          这部分. ./env 将导出它们,然后在您的命令的同一范围内使用它们

          【讨论】:

            【解决方案7】:

            对我来说,我必须在我的 NodeJS 文件中指定路径。

            // did not work!!!!!
            require('dotenv').config()
            

            改为

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

            【讨论】:

              【解决方案8】:

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

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

              【讨论】:

                【解决方案9】:

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

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

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

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

                【讨论】:

                • 你的 crontab 的 $SHELL 已经是 zsh 了吗?我的是 /bin/sh 虽然我使用 zsh 交互。
                【解决方案10】:

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

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

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

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

                【讨论】:

                • 这对我很有用,经过努力寻找答案,谢谢!
                • 这对我不起作用,直到我意识到我忽略了 $HOME 之前的那段时间。这段时间到底是做什么的?
                • 句号相当于“source”命令:tldp.org/LDP/abs/html/special-chars.html#DOTREF
                • @PeterLee 提到的任何内容对您有用吗?我写了这个,因为上述解决方案对我无效。如果上述解决方案不起作用,我将不得不做一些研究以找出原因。 ;-)
                • @Vishal 实际上,它现在对我有用。我试图source ~/.bashrc,结果我的.bashrc 文件与cron 作业有点冲突。如果我使用一个非常简单的.env_setup_rc 文件,只有一行:export MY_ENV_VAR=my_env_val,它确实有效。见我的帖子:stackoverflow.com/questions/15557777/…
                【解决方案11】:

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

                【讨论】:

                • 最佳答案,只需执行env &gt;&gt; /etc/environment,所有当前的环境变量现在都可以在 CRON 作业中使用。
                • 这对我很有用。特别是因为我正在运行 Docker 容器,所以我不太关心“系统范围”的影响。
                • @Savageman 就像用聚变炸弹杀死苍蝇一样,这样做的意外行为风险非常高。
                • 小心:如果其中一个环境变量中有井号,env &gt;&gt; /etc/environment 将失败。我遇到了最困难的故障排除我的应用程序。原来是一个包含“#”的密码,在这一步被截断了。
                • 这应该是选择的答案。我不知道为什么人们将其他答案或关于 env >> /etc/environment.如果您希望这些 env var 普遍可用,只需眨眼就可以编辑 etc/environment:我的实验似乎证实 /etc/environment 中的 env var 的导出语句对 crontab 和用户都可用。问题:再次来自我的实验:这些环境变量似乎没有在 crontab 本身中扩展! ...即它们仅在调用的脚本中扩展!
                【解决方案12】:

                如果您通过 cron 启动正在执行的脚本:

                #!/bin/bash -l
                

                他们应该选择你的~/.bash_profile 环境变量

                【讨论】:

                • 这个答案应该得到更多的支持,并且只是被选中的答案:非常简单和优雅,避免了无数需要在整个系统中跳跃的kludges。
                • 我喜欢这个答案 +1。在运行root 的 crontab 时可以/应该使用它吗?我的系统上没有/home/root 文件夹,所以我看不出这将如何与root 的crontab 一起工作。想法?
                • 在脚本本身中。然后您可以正常使用 cron 运行。
                • @Jim 见this example,经典可执行文件(chmod 777)使用#!/bin/bash。这里的神奇之处在于添加-l
                • 来自 man 的解释:-l 使 bash 表现得好像它已被作为登录 shell 调用(参见下面的 INVOCATION)。
                【解决方案13】:

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

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

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

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

                希望对你有用

                【讨论】:

                  【解决方案14】:

                  代替

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

                  使用 bash -l -c

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

                  【讨论】:

                  • 为什么要这样做,而不是在文件顶部使用 Bash 声明,而不是像这样:-l#!/bin/bash -lThis other answer 简洁大方。
                  • 如果我需要运行 perl/python/ruby 脚本而不是 bash 怎么办?我无法将 #!/bin/bash -l 添加到 python 脚本的顶部。
                  • “如果我需要运行 perl/python/ruby 脚本而不是 bash 怎么办?”很公平。但在我看来,您可以编写一个简单的 Bash 脚本包装器,然后调用 Python 脚本。我为 PHP 脚本做类似的事情。原因是 Bash 中的进程锁定非常好和可靠,但是 Bash 脚本仍然是一个令人头疼的问题。所以我用 PHP 写了一些复杂的东西,让 Bash 处理剩下的。
                  【解决方案15】:

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

                  【讨论】:

                    【解决方案16】:

                    this answer 启发的另一种“注入”变量的方法如下(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 变量以格式化电子邮件标题的示例:

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

                    【讨论】:

                      【解决方案17】:

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

                      【讨论】:

                        【解决方案18】:

                        扩展@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 源之后的任何命令都将拥有您的环境,就像您登录一样。

                        【讨论】:

                          【解决方案19】:

                          从命令行运行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"
                          

                          【讨论】:

                          • 请注意,您不能像在 shell 中那样使用变量替换,因此像 PATH=/usr/local/bin:$PATH 这样的声明会按字面意思解释。
                          • 我能够在 RedHat 4.4.7-3 和 cronie-1.4.4-15.el6.x86_64 下的 crontab 中设置环境变量
                          • 如果变量仅在命令中使用,您实际上不需要导出变量,只需在命令之前添加它们即可。 "* * * * * 休眠 5s;LC_ALL=nb_NO.UTF-8 echo $LC_ALL"
                          • @Zac 你可以使用变量this way(选项3)
                          【解决方案20】:

                          在运行命令之前让“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
                          

                          【讨论】:

                            猜你喜欢
                            • 2017-11-25
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            相关资源
                            最近更新 更多