55

我是使用 cron 和 crontab 安排任务的新手。我正在尝试安排任务的执行,就好像我已经登录、打开终端并自己执行一样。

但是,我安排了一个任务来帮助我观察计划任务正在执行的 $USER 和 $PATH ,这就是我发现的:

$ crontab -l
41 11 * * * echo "USER: $USER" > ~/Desktop/cron_env.log; echo "PATH: $PATH" >> ~/Desktop/cron_env.log
$ cat ~/Desktop/cron_env.log
USER:
PATH: /usr/bin:/bin

看起来好像 $USER 没有设置,并且 $PATH 是非常基本的和/或默认的。相反,这是我打开终端(登录)并回显相同信息时看到的内容:

USER: aschirma
PATH: /usr/lib/jvm/java-6-sun/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/pkg/icetools/bin:/pkg/hwtools/bin:/pkg/netscape/bin:/pkg/gnu/bin

我需要做什么才能让我的 crontab 任务按照我想要的方式运行?

4

5 回答 5

85

根据“man 5 crontab”,您可以在您的 crontab 中设置环境变量,方法是将它们写在您的 cron 行之前。

还有一个 crontab 示例,因此您只需复制/粘贴它:

$ man 5 crontab | grep -C5 PATH | tail 
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow usercommand
17 * * * *  root  cd / && run-parts --report /etc/cron.hourly
25 6 * * *  root  test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7  root  test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )

因此,您可以根据需要调整 PATH 或任何环境变量。但是这个例子对于典型案例来说似乎已经足够了。

于 2013-02-04T19:59:16.513 回答
16

In *ix, processes commonly inherit an environment from their parent process across fork+exec. They have the option of clearing the environment, but usually they don't. You can see the process tree with ps axf, and you can see the environment variables by using ps axfe.

cron is commonly not a child of someone's shell, so it'll often have a different environment from your interactive shell. There's a good chance cron's going to be intentionally clearing its own environment somehow for consistency though.

I like to test my cron jobs ("foo" for the sake of discussion) with the following in an interactive shell: env - ./foo This will actually clear out more env vars that cron does, but it makes it easier to get things going IMO, since what you're testing is more similar. You'll need to set any variables you're depending on (like $PATH), or replace them with something else - EG $USER becomes $(whoami).

I also like to write my bash scripts to use "set -eu" and "set -o pipefail". The -eu says "exit on a nonzero exit code, and exit on an undefined variable reference", and the pipefail says "don't return the last exit code in a pipeline, instead return the first exit code that's nonzero in a pipeline". In your case, the set -u might be particularly helpful.

于 2012-04-12T18:37:17.447 回答
3

记住 crontab 是一个守护进程或服务,所以不像用户登录或其他东西。如果你想拥有你的环境变量,你需要自己设置它们。但是,这些变量中的大多数是由 shell 从 /etc/profile 路径设置的,然后将您的自定义变量放入您的 $HOME 目录中。

您可以通过“采购”您的 /etc/profile 来设置其中的一些,例如:

41 11 * * * /home/<me>/cron_env.sh
其中cron_env.sh将包含以下内容:
#!/bin/sh
source /etc/profile
/usr/bin/env > /home/<me>/cron_env.log

于 2012-04-12T18:29:49.650 回答
3

在我们的环境中,我们通常没有这个问题,因为 root 是唯一允许的 cron 并且每个命令通常作为特定于应用程序的用户通过 su -c 命令运行,如下所示:

su - myuser -c "/usr/local/scripts/app.sh" 2>&1

由于指定了“-”选项,我们得到了 myuser 的配置文件和环境。我们最近遇到了一个需要 root 权限才能成功完成的命令的问题,所以我们只是发出了没有 su -c 的命令。经过一些研究后,我们发现获取 root 环境的最简单方法是对 root 使用与所有其他应用程序相同的技术,因此我们发布了:

su - root -c "/usr/local/scripts/app.sh" 2>&1
于 2015-07-29T20:00:55.033 回答
1

crontab 不是 bash 脚本,您不能使用通常在 shell 中可用的环境变量。

尝试将所有代码移动到 shebang 脚本文件(以“#!/bin/bash”行开头的文件)并在 crontab 中运行该脚本。

我不确定,但我认为 PATH(如果你设置了它,可能是 EMAIL)可能是你可以在 crontab 文件中访问的唯一一个。

编辑:检查crontab 5 手册页,有很多可用的环境变量,全部由 cron 守护程序设置。

于 2012-04-12T18:25:15.457 回答