如何使用现有环境变量运行cron命令?


112

如何使用现有环境变量运行cron命令?

如果我在shell提示下可以键入echo $ORACLE_HOME并获取路径。这是我设置的环境变量之一~/.profile。但是,似乎~/.profile没有加载fron cron脚本,因此我的脚本失败了,因为$ORACLE_HOME未设置变量。

这个问题中,作者提到创建一个~/.cronfile配置文件,该配置文件为cron设置变量,然后他采取了一种变通方法,将所有cron命令加载到他保存在~/Cron目录中的脚本中。像~/.cronfile这样的文件听起来像是个好主意,但其余的答案似乎有点麻烦,我希望有人可以告诉我一种更简单的方法来获得相同的结果。

我想在脚本开始时我可以添加类似的内容,source ~/.profile但这似乎是多余的。

那么,如何使我的cron脚本从交互式shell配置文件中加载变量?


如何添加source ~/.profile程序冗余?程序从调用程序继承其环境。如果该调用程序不是您的shell,那么子程序将如何获得所需的环境?
Arcege 2011年

我已经在这里写下了对类似问题的答案它仅su -l用于为root用户或其他特定用户设置包括$ PATH在内的常规登录环境。
Tasket

Answers:


140

在crontab中,在命令之前添加. $HOME/.profile。例如:

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

Cron对您的外壳一无所知;它是由系统启动的,因此它具有最小的环境。如果您想要任何东西,则需要将其带入自己。


14
什么是.脚本之前呢?(不知道我会怎么man做)。为什么这不同于source
cwd

25
.命令是的原始命令source。它们在Shell中是等效的,并且易于键入,尤其是在crontab中。要获取更多信息,请在手册页中键入help .或搜索zshbuiltins 或在其顶部键入type。`会告诉您该命令是内置命令。^SHELL BUILTIN COMMANDSbashman . Running
Arcege 2011年

9
根据Linux发行版,你可能需要改变.profile.bash_profile。检查.profile用户的主目录中存在哪个文件。
Frosty Z

@Arcege这对我不起作用(Fedora Core 21),我认为那是因为shell级别下降了。取而代之的是,如果您获得了它,它是起作用的。
理查德T

3
如果它不起作用,可能是因为cron脚本的SHELL未设置为bash,所以它的执行方式可能与您期望的不同。
Daniel Farrell

40

我发现更容易的另一种选择是使用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的源之后的任何命令都将具有您所登录的环境。


5
在AWS Linux AMI上运行时,我什至没有想到cron不会/bin/bash用作外壳。我一直想知道为什么cd /path/to/project; source .vars当我手动键入类似的东西时会起作用,但是File not found当包含在cronjob中时却会失败()。对我来说,关键是要进行设置,SHELL=/bin/bash以便实际上可以在每个cronjob中使用熟悉的bash命令。/bin/sh/(显然,默认的cron shell)是非常有限的。
哈特利·布罗迪

太糟糕了,您无法在cron顶部指定环境文件,就像您可以指定各个环境变量一样。Systemd有一个EnvironmentFile服务单元。太糟糕的cron没有类似的东西。
radtek

您强制所有脚本在所有crontab中使用/ bin / bash,这不是一个好主意,关于您的cron行又是什么:* / 1 * * * * $ HOME / cron_job.sh…* / 1可以做什么?!?一星意味着它将被执行每分钟/ 1手段将每隔一分钟执行,如在智能社区,这是一个讨厌的罪,现在我相信你很困惑地说最好...对不起答案
THESorcerer

1
这就是所谓的例子。随意调整以适应您的需求或根本不使用它。物以类聚,人以群分。
罗伯特·布里斯塔

4
如果$SHELL/bin/sh,则该source命令不存在。使用.代替。
梅勒

17

我发现更简单的另一种选择是使用cron运行脚本并告诉bash登录(因此使用/etc/profile.d/...环境定义)

crontab -e文件中:

*/1 * * * * bash -l -c './cron_job.sh'
*/1 * * * * bash -l -c 'php -f ./cron_job.php'

来源之后的任何命令都.bash_profile将具有您所登录的环境。


10

馊主意。通常的做法是在要从cron作业运行的脚本中专门设置所有必需的环境变量。


我同意@fpmurphy,它也可以确保安全的流程环境。如果只想设置cron中的几个变量,则可以使用/usr/bin/env命令来设置变量,然后可以用作cronjob的环境过程。
Nikhil Mulley


6
我全心全意为安全起见,但也许我可以创建一个文件,~/.cronvars并将其包含在配置文件中以及我的cron脚本中。我不想在我运行的每个脚本中对环境变量进行硬编码,因为当路径更改时,每个文件中的硬编码路径都难以维护。似乎这样可以将所需变量集中放置在一个位置,并且仍然避免加载其他变量。
cwd

4

这种语法绝对可以帮助您。我不了解语法,但是可以正常工作。在将Oracle Configuration Manager部署到crontab时,Oracle使用此语法,因此,我认为这是正确的解决方案。

0 5 * * * SOME_ENV_VAR=some_value some_command some_parameters

2

最近,我遇到一个案例,其中我必须以root用户身份执行整个cronjob,但同时又必须以其他用户身份执行子命令(这需要采购该用户的环境)。我采用以下方法:

# m  h  dom  mon  dow  user  command
*/5  *   *    *    *   root  (sudo -i -u <the user> command-to-be-run-as-user) && command-to-be-run-as-root

关键部分是-i传递给sudo该参数的参数,该参数将在单独的登录shell中执行给定命令(这又意味着将获取用户的dotfile)。

PS:请注意,该user列仅在/etc/crontab/etc/cron.d/*文件中可用。


1

这里描述对我有用的解决方案。

您创建一个包装器脚本,该脚本调用. ~/.cronfile,然后执行所需的操作。该脚本由cron启动。

在其中~/.cronfile指定cron作业的环境。


1

是的,您可以使用“众所周知的解决方法”(已列出其中的两个)。这是另一种说法,每个人都知道它是糟糕的,尽管有些人将其称为“安全功能”,因为他们至少花了与您一样多的时间来解决此故障,并想着浪费时间并不是没有。它与QWERTY键盘的cron等效。

我怀疑最初的原因可能是性能,例如脚本每分钟运行一次不会花费时间来读取rc脚本。同样,最初cron根本不是真正可配置的,所以默认确实是唯一的选择。

没有简单的配置或方法让cron仅仅充当交互式shell的环境,而不是用户必须执行愚蠢的shell体操,就不会增加安全性。在现代机器上,除非您每分钟都有大量工作在运行,否则通常不会获得明显的性能提升。

Unix文化失败。在我的愚见。:-)


1
“没有增加的安全性。” 那是不对的。看看CVE-2011-1095CVE-2008-4304CVE-2010-3847

顺便说一下,我拒绝了你的回答。我通常会尽量避免降低新人的答案,但是安全性对我很重要。请不要以错误的方式接受否决票。除了有关安全性的部分外,您的答案非常好,值得推荐。您可以根据需要在此处编辑答案。

这些都与cron使用带有交互式标志集的shell无关。这是纯FUD。不幸的是,我不能投票赞成你。这看起来像是烈火,但是当人们认为带有三个轮子的车辆更好时会感到非常沮丧,因为存在安全问题,因此必须安装第四个轮子。不是。人们刚刚骑了三轮车,直到他们忘记了可以增加第四个轮子。
奥斯汀S.13年

换句话说,如果使用了建议的其他答题者预期的额外篮球,那么他们怎么也无法访问您提到的任何漏洞?“ * * * * * * exec bash -i -c LOCALE = .......”
Austin S.

这听起来像是在咆哮。我什至看不到它在哪里回答了这个问题。即使删除了安全部分,@ EvanTeitelman,我也看不出为什么它不值得回答,为什么值得投票。
通配符


1

除了设置个人资料以外,帮助我设置了PATH。有些命令在我的cron脚本中不可用,因为PATH有所不同。

ENVIRONMENT=prod
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
*/30 * * * * /opt/myscript1.sh
*/30 * * * * /opt/myscript2.sh
*/30 * * * * /opt/myscript3.sh

设置PATH命令路径对我有所帮助。如果您可以使用模板并稍后取消模板化,那就更好了,

ENVIRONMENT={{ENVIRONMENT}}
PATH={{PATH}}
*/30 * * * * /opt/myscript1.sh
*/30 * * * * /opt/myscript2.sh
*/30 * * * * /opt/myscript3.sh

将变量传递给每个项目看起来很混乱。


-1

我放 。~/.dbus/session-bus/*在我想要的脚本的顶部:)


1
欢迎来到U&L SE。请进一步扩展您的答案,以使读者受益。
Ramesh 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.