如何让 CRON 调用正确的路径

我正在尝试让 cron 调用正确的 PATHs。当我从 shell 运行 Python 脚本时,脚本运行良好,因为它使用 bashrc 中设置的 PATHs,但是当我使用 cron 时,所有的 PATHs 都没有从 bashrc 中使用。有没有一个文件,我可以输入的路径到 cron 像 bashrc 或一种方法来调用的路径从 bashrc?

对不起,我不认为我的措辞正确,我可以得到正确的脚本运行(这意味着在 crontab 中的 PATH 脚本不是这里的问题) ,它只是当脚本运行时,我运行一个构建,这使用了在 .bashrc中设置的 PATHs。当我在登录时运行脚本时,.bashrc路径将被拉入。因为 cron 没有在 shell 中运行,所以它没有拉入 .bashrc。有没有一种方法可以不用编写 bash 脚本包装器就可以将这些内容提取出来?

221022 次浏览

你应该把完整的路径放在你的 crontab。这是最安全的选择。
如果不想这样做,可以在程序周围放一个包装器脚本,并在其中设置 PATH。

例如:。

01 01 * * * command

变成:

01 01 * * * /full/path/to/command

此外,从 cron调用的任何内容都应该对其运行的程序非常小心,并且可能为 PATH变量设置自己的选择。

编辑:

如果您不知道要从 shell 执行 which <command>的命令在哪里,它会告诉您路径。

编辑2:

所以一旦你的程序开始运行,它应该做的第一件事就是将 PATH和任何其他需要的变量(例如 LD_LIBRARY_PATH)设置为脚本运行所需的值。
基本上,与其考虑如何修改 cron 环境使其更适合您的程序/脚本,不如让您的脚本在启动时设置一个合适的环境,从而处理给定的环境。

Cron 作业的默认环境非常稀疏,可能与您在其中开发 Python 脚本的环境非常不同。对于可能在 cron 中运行的脚本,应该显式地设置所依赖的任何环境。在 cron 文件本身中,包含到 Python 可执行文件和到 Python 脚本的完整路径。

我用的是 /etc/crontab。我使用 vi并输入我需要的 PATHs 到这个文件中,然后以 root 用户身份运行它。普通的 crontab 会覆盖您已设置的路径。关于如何做到这一点的一个很好的教程.

系统范围的 cron 文件如下所示:

This has the username field, as used by /etc/crontab.
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file.
# This file also has a username field, 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 user   command
42 6 * * *   root    run-parts --report /etc/cron.daily
47 6 * * 7   root    run-parts --report /etc/cron.weekly
52 6 1 * *   root    run-parts --report /etc/cron.monthly
01 01 * * 1-5 root python /path/to/file.py

最有可能的情况是,cron 运行在一个非常稀疏的环境中。检查 cron 正在使用的环境变量,方法是附加一个虚拟作业,该作业将 env转储到一个文件,如下所示:

* * * * * env > env_dump.txt

将其与正常 shell 会话中的 env输出进行比较。

通过在 crontab 的顶部定义自己的环境变量,可以将它们预先放到本地 crontab 中。

下面是将 $PATH添加到当前 crontab 的快速修复方法:

# echo PATH=$PATH > tmp.cron
# echo >> tmp.cron
# crontab -l >> tmp.cron
# crontab tmp.cron

生成的 crontab 看起来类似于 chrissygormley 的答案,在 crontab 规则之前定义了 PATH。

在我的 AIX cron 中,它从/etc/Environment 中获取环境变量,忽略在. profile 中设置的内容。

编辑: 我还检查了几个不同年龄段的 Linux 机器,它们似乎也有这个文件,所以这可能不是特定于 AIX 的。

我使用 joemaller 的 cron 建议检查了这一点,并在/etc/Environment 中编辑 PATH 变量之前和之后检查了输出。

我知道这个问题已经得到了回答,但我认为他的回答对某些人来说是有用的。我最近解决了一个类似的问题(在这里发现的) ,以下是我为回答这个问题而采取的步骤中的一些亮点:

  1. 确保在 PYTHONPATH 中有所需的变量(在这里和这里找到,并在这里获得更多信息)。个人资料或。Bash _ profile 用于您想要测试脚本的任何 shell,以确保它能够工作。

  2. 编辑 crontab 以包含在 cron 作业中运行脚本所需的目录(可以在这里和这里找到)

    A)确保在 PATH 变量(.)中包含根目录正如这里所解释的(基本上,如果您使用命令运行可执行文件,它需要能够找到根目录或存储可执行文件的目录) ,可能还有这些(/sbin:/bin:/usr/sbin:/usr/bin)

  3. 在 crontab 文件中,创建一个 cronjob,它将把目录更改为您以前成功运行脚本的目录(即用户/用户/文档/foo)

    A)情况如下:

    * * * * cd /Users/user/Documents/foo; bar -l doSomething -v
    

如果你不想在不同的地方做同样的编辑,那么粗略地做一下:

* * * * * . /home/username/.bashrc && yourcommand all of your args

那个。空间,然后路径到。Bashrc 和 & & 命令是使您的环境变更进入正在运行的 bash shell 的魔法。另外,如果您真的希望 shell 是 bash,那么在 crontab 中有一行是个好主意:

SHELL=/bin/bash

希望能帮到别人!

问题

当从控制台运行脚本时,脚本可以工作,但在 cron 中失败。

因为

Crontab 没有正确的路径变量(可能还有 shell)

解决方案

添加当前 shell 并路径 crontab

给你写剧本

#!/bin/bash
#
# Date: August 22, 2013
# Author: Steve Stonebraker
# File: add_current_shell_and_path_to_crontab.sh
# Description: Add current user's shell and path to crontab
# Source: http://brakertech.com/add-current-path-to-crontab
# Github: hhttps://github.com/ssstonebraker/braker-scripts/blob/master/working-scripts/add_current_shell_and_path_to_crontab.sh


# function that is called when the script exits (cleans up our tmp.cron file)
function finish { [ -e "tmp.cron" ] && rm tmp.cron; }


#whenver the script exits call the function "finish"
trap finish EXIT


########################################
# pretty printing functions
function print_status { echo -e "\x1B[01;34m[*]\x1B[0m $1"; }
function print_good { echo -e "\x1B[01;32m[*]\x1B[0m $1"; }
function print_error { echo -e "\x1B[01;31m[*]\x1B[0m $1"; }
function print_notification { echo -e "\x1B[01;33m[*]\x1B[0m $1"; }
function printline {
hr=-------------------------------------------------------------------------------------------------------------------------------
printf '%s\n' "${hr:0:${COLUMNS:-$(tput cols)}}"
}
####################################
# print message and exit program
function die { print_error "$1"; exit 1; }


####################################
# user must have at least one job in their crontab
function require_gt1_user_crontab_job {
crontab -l &> /dev/null
[ $? -ne 0 ] && die "Script requires you have at least one user crontab job!"
}




####################################
# Add current shell and path to user's crontab
function add_shell_path_to_crontab {
#print info about what's being added
print_notification "Current SHELL: ${SHELL}"
print_notification "Current PATH: ${PATH}"


#Add current shell and path to crontab
print_status "Adding current SHELL and PATH to crontab \nold crontab:"


printline; crontab -l; printline


#keep old comments but start new crontab file
crontab -l | grep "^#" > tmp.cron


#Add our current shell and path to the new crontab file
echo -e "SHELL=${SHELL}\nPATH=${PATH}\n" >> tmp.cron


#Add old crontab entries but ignore comments or any shell or path statements
crontab -l | grep -v "^#" | grep -v "SHELL" | grep -v "PATH" >> tmp.cron


#load up the new crontab we just created
crontab tmp.cron


#Display new crontab
print_good "New crontab:"
printline; crontab -l; printline
}


require_gt1_user_crontab_job
add_shell_path_to_crontab

来源

Https://github.com/ssstonebraker/braker-scripts/blob/master/working-scripts/add_current_shell_and_path_to_crontab.sh

样本输出

add_curent_shell_and_path_to_crontab.sh example output

将 PATH 定义添加到具有正确值的用户 crontab 中将有助于..。 我在顶部(评论之后,cron 作业之前)填写了这一行:

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

这足以让我所有的脚本工作... 包括任何自定义路径,如果你需要的。

在 crontab 中的命令行之前设置 PATH 对我来说很有用:

* * * * * PATH=$PATH:/usr/local/bin:/path/to/some/thing

让你的变量为你工作,这将允许访问 t

在/etc/profile.d/* . sh 中定义 PATH

全系统环境变量

文件。只要输入 bash 登录 shell (例如,从控制台或通过 ssh 登录) ,就会执行/etc/profile.d 目录中的 sh 扩展,桌面会话加载时也会执行 DisplayManager。

例如,您可以创建文件/etc/profile.d/myenvvars.sh 并设置如下变量:

export JAVA_HOME=/usr/lib/jvm/jdk1.7.0
export PATH=$PATH:$JAVA_HOME/bin

执行带登录选项的 crontab!

CRONTAB 使用 Environment Variables 运行脚本或命令

0 9 * * * cd /var/www/vhosts/foo/crons/; bash -l -c 'php -f ./download.php'
0 9 * * * cd /var/www/vhosts/foo/crons/; bash -l -c download.sh

@ Trevino: 你的回答帮助我解决了我的问题。然而,对于一个初学者来说,尝试给出一个一步一步的方法。

  1. 通过 $ echo $JAVA_HOME获取当前的 Java 安装
  2. $ crontab -e
  3. * * * * * echo $PATH-这可以让您了解目前 crontab 使用的 PATH 值是什么。运行 crontab 并获取 crontab 使用的 $PATH 值。
  4. 现在再次编辑 crontab 来设置您想要的 java bin 路径: a) crontab -e; b) PATH=<value of $JAVA_HOME>/bin:/usr/bin:/bin(它是一个示例路径) ; c)现在您的预定作业/脚本如 */10 * * * * sh runMyJob.sh &; d)从 crontab 中删除 echo $PATH,因为它现在不需要了。

如果你使用 webmin,下面是如何设置 PATH值的步骤:

System
-> Scheduled Cron Jobs
-> Create a new environment variable
-> For user: <Select the user name>
-> Variable name: PATH
-> Value: /usr/bin:/bin:<your personal path>
-> Add environment variable: Before all Cron jobs for user

在 cron 中设置所需的 PATH

crontab -e

编辑: 按 i

PATH=/usr/local/bin:/usr/local/:or_whatever


10 * * * * your_command

保存并退出 :wq

我发现的最简单的解决方法是这样的:

* * * * * root su -l -c command

此示例以 root 用户的身份调用 su,并使用用户的完整环境(包括 $PATH)启动 shell,设置它们就像已经登录一样。它在不同的发行版上工作原理相同,比源代码更可靠。Bashrc (这对我来说不起作用) ,避免硬编码特定的路径,如果你提供一个示例或安装工具,不知道什么发行版或文件布局的用户的系统可能是一个问题。

如果希望使用与 root 不同的用户,还可以在 su之后指定用户名,但是可能应该在 su命令之前保留 root参数,因为这样可以确保 su有足够的权限切换到您指定的任何用户。