在 cronjob 中加载用户环境变量

在 cronjob 中加载用户环境变量

如何在 cronjob 中加载用户环境变量?


我有一个 cronjob,它应该在我的 Ubuntu 机器上每分钟启动一个脚本:

* * * * * /home/user/myscript.sh;

在此脚本中,我想使用环境变量(如$JAVA_HOME和 )$M2_HOME来自动启动构建过程。问题是这些变量是在.bashrcvia中设置的export JAVA_HOME=/../..

因此,我source在执行脚本之前要保存这些文件:

* * * * * source ~/.bash_profile; source ~/.bashrc; /home/user/myscript.sh;

但是,变量没有设置!为了测试这一点,我通过日志文件将echo环境变量设置为:env

env >> ~/env.log
echo $M2_HOME >> ~/env.log

日志文件仍然不包含变量。只有以下内容附加到文件(没有$M2_HOME等):

LANGUAGE=en_US:en
HOME=/home/user
LOGNAME=user
PATH=/usr/bin:/bin
LANG=en_US.UTF-8
SHELL=/bin/sh
PWD=/home/user

如果我在我的 shell 中运行脚本,所有变量都会打印出来env.log

source当我将命令放入脚本文件时,也会发生同样的情况。只有删除export变量声明前的关键字,echo $var命令才会看到它。但这不是一个解决方案,因为我不管理这些声明。


我尝试了@tripplee 的解决方案,但 sh shell 问题有限,仍然不起作用。我进一步将其简化为一个非常简单的 cronjob,无需第二个脚本来显示问题所在:

* * * * * . $HOME/.bash_profile; . $HOME/.bashrc; env > $HOME/env.log;

cat /home/user/env.log

LANGUAGE=en_US:en
HOME=/home/user
LOGNAME=user
PATH=/usr/bin:/bin
LANG=en_US.UTF-8
SHELL=/bin/sh
PWD=/home/user

答案1

cron 作业语法仅限于,sh因此您不能使用诸如 之类的 Bashism ~。幸运的是,修复很容易 - 只需将其替换为$HOME。同样,source需要将其替换为.(只是一个点)。

当然,如果您打算从 中使用脚本,则您提供的脚本也不能使用 Bash 语法sh。 最简单的解决方法可能是将这些内容迁移到您的脚本中(或为 Cron 运行创建包装器脚本)。

因为在你的脚本里面,你可以bash随意使用,当然前提是 shebang 行是正确的#!/bin/bash(如果需要的话调整路径)而不是#!/bin/sh

如果由于某种原因您不喜欢这样做,您可以crontab通过明确指定在文件中内联 Bash:

* * * * * bash -c 'source ~/.bash_profile; source ~/.bashrc; ./myscript.sh'

当出现问题时,您应该能够看到source: command not foundexport: command not found收到发送的电子邮件。检查错误输出对于故障排除非常重要。cron

当然,如果您在 Ubuntu 上安装了标准.bashrc,当您尝试从非交互式脚本获取它时,它会立即退出。也许最好将您想要的非交互式使用设置放在另一个文件中(也许默认情况.profile下会读取该文件sh)?

答案2

为了补充 tripleee 的答案,您可以通过在 crontab 中指定 shell 来在 bash(或您选择的 shell)中评估所有 cron。

SHELL=/bin/bash
* * * * * . $HOME/.bash_profile; . $HOME/.bashrc; env > $HOME/env.log;

编辑如果你真的想看看它在做什么,以下命令应该可以使其足够详细:

/bin/bash -x -c '. $HOME/.bash_profile; . $HOME/.bashrc; env > $HOME/env.log' > /tmp/cron.`date +\%s` 

set -x或者命令行上的 -x 标志将导致大多数 shell 打印所评估的每一行。

要在命令行上测试,请从 date 命令中删除 \。这是为了防止 cron 将 %s 评估为标准输入。

答案3

你没有cron 中的完整 tty。但如果你通过它运行,sudo -i你就会得到一个。

* * * * * sudo -u user -i bash -c '. $HOME/.bash_profile; . $HOME/.bashrc; env > $HOME/env.log;'

或者启动脚本:

* * * * * sudo -u user -i bash -c '. $HOME/.bash_profile; . $HOME/.bashrc; /home/user/myscript.sh;'

如果你把source命令放在猛击启动目标脚本的脚本你会得到一个整洁的:

* * * * * sudo -u user -i /home/user/mystarter.sh;

相关内容