321

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

我试过把它们放进去.profile.bashrc但它们似乎仍然没有被捡起。有谁知道我可以在哪里放置 crontab 可以获取的环境变量?

4

20 回答 20

282

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"
于 2012-05-18T17:26:21.110 回答
179

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

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

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

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

于 2012-11-27T08:08:28.420 回答
95

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

于 2015-12-28T11:47:59.453 回答
93

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

'daily' 命令更简单:

:       "@(#)$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
于 2010-02-09T14:43:16.993 回答
68

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

#!/bin/bash -l

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

于 2018-07-30T10:18:19.443 回答
27

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

于 2013-09-05T22:42:12.453 回答
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"

我希望这有帮助!

于 2014-09-08T11:57:04.780 回答
16

您设置的任何内容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
...
于 2016-05-12T10:11:47.080 回答
8

代替

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

使用 bash -l -c

0  *  *  *  *  bash -l -c 'sh /my/script.sh'
于 2018-03-03T15:17:41.947 回答
8

你也可以在你的命令前面加上env注入环境变量,如下所示:

0 * * * *   env VARIABLE=VALUE /usr/bin/mycommand
于 2020-02-20T13:19:31.963 回答
7

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

在 crontab -e 文件中:

SHELL=/bin/bash

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

在脚本.sh

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

some-other-command
于 2014-03-20T13:37:12.890 回答
4

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

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

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

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

于 2019-08-28T16:11:18.253 回答
2

另一种方法-受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
于 2015-03-06T15:23:37.370 回答
2

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

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

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

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

我希望这变得有用

于 2018-09-01T14:48:04.533 回答
2

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

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

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

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

于 2020-11-11T09:39:30.060 回答
1

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

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

反而

// DID WORK!!
require('dotenv').config({ path: '/full/custom/path/to/your/.env' })
于 2020-10-04T13:43:51.850 回答
1

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

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

我找到了解决方案:

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

于 2020-12-02T15:26:45.320 回答
1

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

FOO=bar
BAZ=qux

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

0 5 * * * export $(xargs < $HOME/.env); /path/to/command/to/run
于 2021-08-06T15:23:09.310 回答
0
  • 设置全局环境
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"

=)

于 2020-11-12T15:54:33.703 回答
0

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

  1. 创建一个包含所有需要的 env var 的文件:

    #!/bin/bash
    环境 | grep VAR1= > /etc/environment
    env | grep VAR2= >> /etc/environment
    env | 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
    服务 cron 启动

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

于 2021-03-31T09:42:16.293 回答