【问题标题】:crontab PATH and USERcrontab 路径和用户
【发布时间】:2012-04-25 03:24:11
【问题描述】:

我是使用 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 任务按我想要的方式运行?

【问题讨论】:

    标签: linux cron crontab


    【解决方案1】:

    在我们的环境中,我们通常不会遇到此问题,因为 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
    

    【讨论】:

      【解决方案2】:

      根据“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 或任何环境变量。但是这个例子对于典型案例来说似乎已经足够了。

      【讨论】:

      • 有没有办法做类似PATH=$PATH:/usr/local/bin的事情?
      • @CMCDragonkai:根据man 5 crontab,“不为环境替换或变量替换解析值字符串”。但是您可能应该将代码编写在单个可执行文件中(通常是.sh,但为什么不使用 C ou Python 呢?),从 crontab 调用您的可执行文件,并让可执行文件自己增加其 $PATH。
      • 这为我解决了community.letsencrypt.org/t/…
      • 关于man 5的TIL,完整的解释见unix.stackexchange.com/questions/3586/…
      • FWIW, crontab(5) from cronie 没有明确提及PATH 变量,而是声明了“An active line in a crontab is either an environment setting or a cron command”,因此这里支持任何环境变量(包括PATH
      【解决方案3】:

      在 *ix 中,进程通常通过 fork+exec 从其父进程继承环境。他们可以选择清除环境,但通常不会。 ps axf可以看到进程树,ps axfe可以看到环境变量。

      cron 通常不是某人的 shell 的子代,因此它通常具有与您的交互式 shell 不同的环境。不过,cron 很有可能会故意以某种方式清除自己的环境以保持一致性。

      我喜欢在交互式 shell 中使用以下内容来测试我的 cron 作业(“foo”以供讨论): 环境 - ./foo 这实际上将清除 cron 所做的更多环境变量,但它使 IMO 更容易进行,因为您正在测试的内容更相似。您需要设置您所依赖的任何变量(例如 $PATH),或者将它们替换为其他变量 - 例如 $USER 变为 $(whoami)。

      我还喜欢编写我的 bash 脚本来使用“set -eu”和“set -o pipefail”。 -eu 表示“在非零退出代码上退出,并在未定义的变量引用上退出”,而 pipefail 表示“不要返回管道中的最后一个退出代码,而是返回管道中非零的第一个退出代码” .在您的情况下, set -u 可能特别有用。

      【讨论】:

      • +1 用于测试...我man env'd 寻找有关单破折号的信息。我希望它包含在-i, --ignore-environment 行中,而不是在描述部分的底部,我完全掩盖了它。
      【解决方案4】:

      记住 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
      

      【讨论】:

      • 以上所有对我都不起作用,所以我只是在我的 bash 文件中添加了 Source 并且它起作用了!谢谢
      【解决方案5】:

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

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

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

      编辑:检查crontab 5 man page,有很多可用的环境变量,都是由cron守护进程设置的。

      【讨论】:

      • 在这里操作。从 cron 启动的脚本没有继承正确的 PATH。事实上,这就是我第一次遇到问题的地方:从 cron 执行的 bash 脚本没有在 PATH 中找到东西,因为 PATH 不正确。
      • @AdamS 这就是问题所在,它们继承了 cron 守护进程提供的 PATH(和其他一些变量),这与您从登录 shell 获得的不同,您可以在 crontab 文件中设置 PATH如果你愿意。
      • 来自手册页:The value string is not parsed for environmental substitutions or replacement of variables, thus lines like PATH = $HOME/bin:$PATH will not work as you might expect.
      猜你喜欢
      • 2014-10-27
      • 2014-02-20
      • 2015-11-12
      • 2016-12-17
      • 2021-06-12
      • 1970-01-01
      • 2012-09-21
      • 2017-06-02
      • 2010-12-26
      相关资源
      最近更新 更多