cron会忽略“ .bashrc”和“ .bash_profile”中定义的变量


49

我在/ etc / crontab文件中定义了“ SHELL”变量:

[martin@martin ~]$ grep SHELL /etc/crontab 
SHELL=/usr/local/bin/bash
[martin@martin ~]$ file /usr/local/bin/bash
/usr/local/bin/bash: ELF 32-bit LSB executable, Intel 80386, version 1 (FreeBSD), dynamically linked (uses shared libs), for FreeBSD 8.0 (800107), stripped
[martin@martin ~]$ 

另外,我在/ etc / crontab文件中的所有脚本都在用户“马丁”下启动。但是/home/martin/.bash_profile(用于登录shell)和/home/martin/.bashrc(用于非登录shell)包含一些变量,这些变量在cron作业的情况下会被忽略,但是在我登录到计算机上方时使用SSH或打开新的bash会话。为什么cron会忽略这些变量?cron是否只是简单地执行具有用户“马丁”权限的“ / usr / local / bin / bash my-script.sh”?


2
Ubuntu用户可能会注意到,Ubuntu的默认设置.bashrc包含一行内容,该行会阻止它在非交互式shell中运行
joeytwiddle

Answers:


72

您可以在脚本顶部或作业开始处为执行作业的用户提供所需的文件。“源”命令是内置命令。如果您对这些文件进行了编辑以加载更改,则您将执行相同的操作。

* * * * * source /home/user/.bash_profile; <command>

要么

#!/bin/bash
source /home/user/.bash_profile

<commands>

2
请注意,如果cron不使用bashshell ,则“源”可能不起作用。我添加了一个可以处理shell为的情况的答案sh
乔纳森


23

因为它不是交互式外壳。当您打开某些终端时,也会发生同样的情况。

看一下这个问题:什么是.bashrc文件?| 超级用户

并且在这一点上:

.bashrc,.bash_profile和.environment有什么区别?| 堆栈溢出

根据连接是登录外壳程序(或不是登录外壳程序),交互式外壳程序(或不是交互式外壳程序)或两者都是,会触发不同的脚本。

如果要制作bashrc,则需要进行以下更改:

例如,以非交互方式启动Bash时,要运行shell脚本,它将在环境中查找变量BASH_ENV,如果变量BASH_ENV出现在环境中,则会对其进行扩展,并将扩展后的值用作读取和执行的文件名。Bash的行为就像执行以下命令一样:

if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi 

但是PATH变量的值不用于搜索文件名。

如上所述,如果使用该--login选项调用非交互式外壳,则Bash尝试从登录外壳启动文件中读取和执行命令。

来源:Bash启动文件| Bash参考手册| gnu.org


因此,如果我们在Cron中设置BASH_ENV,则cron bash脚本将提供该信息,因为cron是非交互式的且非登录的。
CMCDragonkai 2015年

12

source如果sh正在使用外壳程序,则可能无法运行。可以通过在crontab中添加以下行来更改此设置:

SHELL=/bin/bash
* * * * * source "/root/.bashrc"; <command>

您还可以指定环境:

BASH_ENV="/root/.bashrc"
* * * * * <command>

或者,/home/user/.bashrc如果您是本地cron作业,则可以使用本地(例如crontab -e)。

注意,.bash_profile可以替换.bashrc,如果存在的话。

信用:如何将cron shell(sh更改为bash)?


这对于Acquia Cloud Scheduled作业(基本上是cron作业)也很有效。您可以执行相同操作,例如:SHELL=/bin/bash && source /home/YOUR_USER_NAME/.bash_profile && sh ....
Alejandro Moreno

1

可能会干扰您.bashrc从cronjob 采购的其他事情是,此文件为检测交互式外壳而进行的任何检查。

例如,在Ubuntu 18.04上,.bashrc用户的默认设置以此开头:

# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

因此采购它不会做任何有用的事情,因为它将立即退出。


1

您可以使用该-l选项调用bash ,如下所示:

* * * * * /bin/bash -l /path/to/script arg1 arg2

-l选项使bash成为登录 shell。因此,它将读取用户的.bash_profile.bashrc除非它由明确来源,否则它将不会读取用户的内容.bash_profile。这是因为非交互式shell不会自动读取.bashrc。但是您不需要.bashrc进行cron作业,因为它.bashrc是用于设置对交互式 Shell 有用的东西。

变化:

如果bash在PATH上,则无需指定绝对路径:

* * * * * bash -l /path/to/script arg1 arg2

一种优化方法是使用以下命令替换当前的shell exec

* * * * * exec bash -l /path/to/script arg1 arg2

1

bash无论是Shell还是普通的编程语言(如perlpython),其行为都不同。

按照设计,在设置中~/.bash_profile~/.bashrc等是当用户设置的东西bash起到一个壳的作用(登录shell,interractive壳)。考虑一下xterm(交互外壳程序)或ssh会话(登录外壳程序)或控制台(登录外壳程序)中的环境。

另一方面,bash它也是一种功能强大的编程语言 -考虑许多用于管理服务的脚本systemd-这需要不同的工作方式。例如,当开发人员编写系统脚本或bash程序时,他/她将不希望~/.bash_profile自动获取用户的资源。这是一个普通程序,而不是外壳程序。普通程序(包括bash程序)自然会从当前的工作环境(shell)继承设置,但不会进行设置

如果我们为cronin 编写程序,bash它恰好是在in编写的bash;其实,我们可以把它写pythonperl或其他任何预设电台语言-那么我们就可以有一个选择来源bash~/.bash_profile(阅读:用户的shell,这恰好是你的编程语言相同的语言的设置):

[ -f /home/user/.bash_profile ] && . /home/user/.bash_profile

但是,如果该特定用户不将其bash用作外壳,该怎么办?他/她可以使用zshkshfish等,所以,这种做法不会真正用于公共用途编写程序时工作。

因此,~/.bash_profile如果您认为可行的话,可以寻求帮助。但是,在这里,这与我们是否能够获取文件无关,而与事物在系统中的工作方式有关:设计概念。简而言之:我们应该将其bash视为具有两个角色:shell和编程语言。这样,一切都会更容易理解。


0

从使用NVM的cron执行节点应用程序时,我遇到了同样的问题,为了使bash shell从cron读取.bashrc文件,只需使用交互式shell选项`-l调用bash命令即可。

例如: * * * * * /bin/bash -lc '/home/user/myapp.sh restart'

如果这样不起作用,请尝试在crontab中设置路径变量

41 7 * * * /bin/bash -lc "PATH=$PATH:/home/user/.nvm/versions/node/v8.10.0/bin && /home/user/script.sh restart "

-1

我的处理方式是:

1)将我的变量放在(的结尾)~/.profile

myVarInDotProfile="someValue"

2)为我的(日常)cron任务(创建一个Bash脚本,~/cronDaily.sh其中包含我的命令以及以下内容的重复来源~/.profle

source ~/.profile
command ${myVarInDotProfile}/

3)从安排我的脚本的执行crontab,以每天运行:

0 0 * * * bash ~/cronDaily.sh

我的变量没有被忽略,命令成功运行。


有人可能会说,如此密集的采购存在~/.profile问题。在我的特殊情况下,我看不出为什么会出现问题,但是建议您考虑为此创建专用文件。

通常,可能有更好的方法,但这是经过很多痛苦后对我有用的方法,它解释了从Bash 4.3.46开始,您不能从中获取文件的原理crontab

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.