在Cron作业中加载环境变量

在Cron作业中加载环境变量

介绍

当crontab运行一个命令时,它不会从~/.bashrc、~/.bash_profile等文件中读取任何环境变量。因为cron从一个非交互式、非登录的shell中运行任务,所以它不需要一个交互式用户 一些应用程序需要环境变量才能正常运行。

我们将讨论从crontab加载环境变量的不同方法。

设置BASH_ENV变量

我们可以通过使用BASH_ENV变量为我们的shell脚本设置环境变量。我们对它进行设置,以便当我们运行作业时,它们由shell脚本来执行。我们可以设置我们的shell,这样当我们打开一个新的终端窗口时,我们就可以得到适合我们系统的设置。我们可以使用BASH_ENV来运行任何shell命令,而不需要知道它的确切名称。

我们将在我们的crontab文件中添加一行,在执行脚本之前运行/etc/profile。

* * * * * BASH_ENV=/etc/profile /home/baeldung/print_envs.sh

注意,这个工作每分钟运行一次。另外,让我们编写/home/baeldung/print_envs.sh脚本,使用printenv–将所有环境变量打印到一个时间文件中。

#!/bin/bash
printenv > /tmp/print_envs_result
Now, after setting execution permission to the script with chmod +x /home/tpoint/print_envs.sh, we’ll wait one minute to see the result:
wc -l /tmp/print_envs_result
38 /tmp/print_envs_result grep PS1= /tmp/print_envs_result
PS1=\u@\h:\w\$

我们可以看到,print_envs脚本加载了38个环境变量。例如,它加载了PS1的值。

你也可以使用BASH_ENV来运行一个自定义的shell命令。我们可以用它来加载多个文件或添加更多的变量。让我们创建一个叫做preload.sh的shell文件,它可以加载四个不同的文件。/etc/profile、~/.bash_profile、~/.bashrc,并导出另一个变量。

#!/bin/bash
. /etc/profile
. ~/.bash_profile
. ~/.bashrc
export LEARNING_FROM=tpoint

现在,我们将修改crontab文件以使用/home/tpoint/preload.sh —

* * * * * BASH_ENV=/home/tpoint/preload.sh /home/tpoint/print_envs.sh

等待一分钟后,我们得到的结果是 —

$ wc -l /tmp/print_envs_result
41 /tmp/print_envs_result
$ grep LEARNING_FROM /tmp/print_envs_result
LEARNING_FROM=tpoint

我们已经注意到,现在有41个环境变量。我们还有一个变量LEARNING_FROM,默认值为 “tpoint”。

用Bash包装工作

假设我们有这样一个crontab文件 —

* * * * * printenv > /tmp/print_envs_result

因为printenv不是一个shell脚本,我们不能用BSH_ENV来加载环境变量值。然而,我们可以用Bash来包装它。我们的做法是在命令前加上bash -c,然后用双引号字符串来包装它。

我们通过在作业前加上bash -c并将作业置于双引号内来实现这一目的。Bash在从传递给脚本的参数中读取命令时使用-c选项。

我们将在我们的脚本中加入bash -c,这样我们就可以检查环境变量BASH_ENV。

* * * * * BASH_ENV=/etc/profile bash -c "printenv > /tmp/print_envs_result"

cron运行作业后,我们可以看到printenv从/etc/profile中加载了所有的环境变量—-。

$ wc -l /tmp/print_envs_result
38 /tmp/print_envs_result
$ grep PS1= /tmp/print_envs_result
PS1=\u@\h:\w\$

如果需要,我们可以添加更多的环境变量,或者我们可以创建另一个shell文件来包括我们想要的额外文件。现在,我们有两个选择。我们可以通过设置一个名为BASH_ENV的环境变量来加载更新的脚本。就像以前一样。相反,让我们把原来的作业从crontabs文件中的当前位置移到我们新的shell脚本的末尾。

让我们创建一个新的shell脚本,称为/home/tpoint/wrap_printenvs.sh –

#!/bin/bash
. /etc/profile
. ~/.bash_profile
. ~/.bashrc
export LEARNING_FROM=tpoint
 
#now, we run the original job
printenv > /tmp/print_envs_result

最后,我们修改crontab文件,以运行新的脚本 —

* * * * * /home/tpoint/wrap_printenv.sh

与上一节类似,我们可以在结果中看到环境变量——。

$ wc -l /tmp/print_envs_result
41 /tmp/print_envs_result
$ grep LEARNING_FROM /tmp/print_envs_result
LEARNING_FROM=tpoint

使用登录外壳运行作业

为了模仿运行crontab条目时的相同顺序,我们可以使用解释器(例如bash)来运行脚本。当Bash作为登录外壳工作时,它会读取诸如~/.bash_profile、~/.bash_login、/etc/profile和~/.profile等文件。这样,bash shell将加载所有的启动脚本,从这些文件中加载环境变量。我们应该用bash -l -c开始工作,并确保用双引号将其括起来。当我们希望命令处于登录(或交互)模式时,-l参数是必不可少的。

让我们用一个交互式的shell来运行上一节的printenv命令。

* * * * * bash -l -c "printenv > /tmp/print_envs_result"

因为这仍然是一个非交互式终端,bash并没有加载~/.bashrc文件。如果我们也使用BASH_ENV,就可以克服这个问题。

我们将用它来加载~/.bashrc和登录外壳。

* * * * * BASH_ENV=~/.bashrc bash -l -c "printenv > /tmp/print_envs_result"

我们现在需要让cron运行该脚本,然后检查是否有任何环境变量被设置。

$ wc -l /tmp/print_envs_result
41 /tmp/print_envs_result

设置Crontab文件中的每个变量

我们可以在运行命令前使用name=variable语法来设置变量。如果我们想使用多个变量,必须用空格分隔。

我们需要为运行print_envs脚本设置环境变量——。

* * * * * LEARNING_FROM=tpoint LANG=es_US /home/tpoint/print_envs.sh

一分钟后,我们现在可以看到脚本将这些值加载到页面中 —

$ grep -E 'LANG|LEARNING_FROM' /tmp/print_envs_result
LEARNING_FROM=tpoint
LANG=en_US

如果我们想设置很多变量,那么我们最后会有很长的一行代码。如果我们这样做,那么这个cron job可能就很难理解了。

像Fedora和Arch Linux这样的程序,提供了cron daemon的实现;通过这些实现,我们可以在/etc/crontab文件中为所有工作(包括系统范围)定义环境变量。我们将每个环境变量一次性写在一行中,其中没有任何作业。

我们将为所有工作类型定义LEARNING_FROM和LANG

LEARNING_FROM=tpoint
LANG=es_US
* * * * * /home/baeldung/print_envs.sh

正如我们所看到的,该脚本加载了这些变量 —

$ grep -E 'LANG|LEARNING_FROM' /tmp/print_envs_result
LEARNING_FROM=baeldung
LANG=en_US

结论

我们研究了为cron job设置环境变量值的不同方法。

我们之前探讨了如何利用$ BASH_ENV环境变量在工作开始前运行一个脚本。这个设置允许我们包括来自其他来源的环境变量,比如/etc/bashrc。

接下来,我们看到,我们可以将一个作业包裹在另一个作业中,在执行原始作业之前,我们设置并加载所有需要的环境变量。

现在我们已经学会了如何单独设置环境变量值,将它们直接写入crontabs文件中。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程

Linux 基础