我试图让 cron 调用正确的路径。当我从 shell 运行 Python 脚本时,脚本运行良好,因为它使用 bashrc 中设置的 PATH,但是当我使用 cron 时,所有 PATH 都没有从 bashrc 中使用。是否有一个文件我可以像 bashrc 一样为 cron 输入 PATH 或从 bashrc 调用 PATH 的方法?
抱歉,我认为我的措辞不正确,我可以运行正确的脚本(这意味着 crontab 中脚本的 PATH 在这里不是问题),只是在该脚本运行时我运行了一个构建,这使用.bashrc
中设置的 PATH。当我登录后运行脚本时,会拉入 .bashrc
路径。由于 cron 不会在 shell 中运行,因此它不会拉入 .bashrc
。有没有一种方法可以在无需编写 bash 脚本包装器的情况下将其引入?
source /etc/profile
,它应该吃掉 .bashrc
和许多其他可能为您丢失的东西。如果您希望某些脚本“独立”运行,则显式配置文件来源非常有用,它还可以防止奇怪的环境等等......
sh
脚本工作。您可以通过添加类似 * * * * * echo $PATH > ~/crontab_path.txt
的作业并在一分钟后检查文件来确认它是否更新了路径。
我使用了 /etc/crontab
。我使用 vi
并在此文件中输入了我需要的 PATH 并以 root 身份运行它。正常的 crontab 会覆盖您设置的 PATH。 A good tutorial on how to do this。
系统范围的 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 。
您应该将完整路径放入您的 crontab
。这是最安全的选择。
如果您不想这样做,可以在程序周围放置一个包装脚本,并在其中设置 PATH。
例如
01 01 * * * command
变成:
01 01 * * * /full/path/to/command
此外,从 cron
调用的任何程序都应该非常小心它运行的程序,并可能为 PATH
变量设置自己的选择。
编辑:
如果您不知道要从 shell 执行 which <command>
的命令在哪里,它会告诉您路径。
编辑2:
因此,一旦您的程序运行,它应该做的第一件事就是将 PATH
和任何其他必需的变量(例如 LD_LIBRARY_PATH
)设置为脚本运行所需的值。
基本上而不是考虑如何修改 cron 环境以使其更适合您的程序/脚本 - 通过在启动时设置一个适当的环境,使您的脚本能够处理给定的环境。
crontab
。
type
和/或 command
而不是 which
和 whereis
等非标准实用程序。有时它们存在并起作用,有时它们不存在。
将 PATH 定义添加到具有正确值的用户 crontab 将有所帮助...我已经在顶部填充了这一行(在评论之后,在 cron 作业之前):
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
这足以让我的所有脚本正常工作......如果需要,请在其中包含任何自定义路径。
/etc/crontab
。这是用户级别上最简单的答案。干得好@Treviño。如果您同意,请投票。
PATH
和系统的默认 PATH
进行比较,并进行相应调整。例如,/usr/local/sbin
有点不寻常,但在 OP 的系统上可能是正确的。带有 sbin
的那些往往是管理命令,对于普通用户,它们通常不在默认的 PATH
上,因此您可能不需要这些命令。
/opt/acme
之类的位置,因此您需要添加 /opt/acme/bin
或者可能是 /opt/acme/ajax/bin
以将它们添加到您的 PATH
中。或者,当然,为了快速而肮脏的一次性,只需硬编码您要运行的二进制文件的位置,例如 /opt/acme/ajax/bin/anvil
而不是 anvil
。
在我的 crontab 中的命令行之前设置 PATH 对我有用:
* * * * * PATH=$PATH:/usr/local/bin:/path/to/some/thing
让你的变量为你工作,这将允许访问
在 /etc/profile.d/*.sh 中定义您的 PATH
System-wide environment variables
每当输入 bash 登录 shell 时(例如,从控制台或通过 ssh 登录时)以及在桌面会话加载时由 DisplayManager 执行,/etc/profile.d 目录中具有 .sh 扩展名的文件都会被执行。
例如,您可以创建文件 /etc/profile.d/myenvvars.sh 并设置如下变量:
export JAVA_HOME=/usr/lib/jvm/jdk1.7.0
export PATH=$PATH:$JAVA_HOME/bin
使用登录选项执行 crontab!
CRONTAB run script or command with 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
/etc/profile.d
是 Debian 的一项发明。对于具有此目录的系统,这是隐约合理的,尽管并非以任何方式具体到 cron
作业;因此,您可能希望避免污染无关工作的环境,并寻求不同的解决方案。
问题
您的脚本在您从控制台运行时有效,但在 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://i.stack.imgur.com/VHOro.png
我发现的最简单的解决方法如下所示:
* * * * * root su -l -c command
此示例以 root 用户身份调用 su
并使用用户的完整环境(包括 $PATH)启动 shell,就像他们已登录一样。它在不同发行版上的工作方式相同,比采购 .bashrc(没有t 为我工作)并避免硬编码特定路径,如果您提供示例或设置工具并且不知道用户系统上的发行版或文件布局,这可能是一个问题。
如果您想要与 root 不同的用户,您还可以在 su
之后指定用户名,但您可能应该在 su
命令之前保留 root
参数,因为这可以确保 su
有足够的权限切换到您指定的任何用户.
cron 作业的默认环境非常稀疏,可能与您在其中开发 python 脚本的环境有很大不同。对于可能在 cron 中运行的脚本,您所依赖的任何环境都应该明确设置。在 cron 文件本身中,包含 python 可执行文件和 python 脚本的完整路径。
在我的 AIX cron 上,它从 /etc/environment 获取它的环境变量,而忽略了 .profile 中设置的内容。
编辑:我还检查了几个不同年龄的 Linux 机器,这些机器似乎也有这个文件,所以这可能不是特定于 AIX 的。
我使用 joemaller 的 cron 建议检查了这一点,并在编辑 /etc/environment 中的 PATH 变量之前和之后检查了输出。
如果您不想在不同的地方进行相同的编辑,那么大致这样做:
* * * * * . /home/username/.bashrc && yourcommand all of your args
这 。空间,然后是 .bashrc 的路径和 && 命令是让你的环境更改到正在运行的 bash shell 中的魔法。同样,如果你真的希望 shell 是 bash,那么在你的 crontab 中有一行是个好主意:
SHELL=/bin/bash
希望它可以帮助某人!
.bashrc
主要是交互式 shell 调用的配置,因此通常包含与 cron
作业无关且可能不适合的内容。一个更有原则的解决方案是将您想要的设置分解到一个单独的文件中,然后从其他各个位置 .
(源)该文件,即您的 cron
作业和您的 .profile
等。
@Trevino:您的回答帮助我解决了我的问题。但是,对于初学者来说,尝试给出一步一步的方法。
通过 $ echo $JAVA_HOME $ crontab -e * * * * * echo $PATH 获取您当前的 java 安装 - 这可以让您了解 crontab 目前使用的 PATH 值是什么。运行 crontab 并获取 crontab 使用的 $PATH 值。现在再次编辑 crontab 以设置您想要的 java bin 路径: a) crontab -e; b) PATH=<$JAVA_HOME 的值>/bin:/usr/bin:/bin(它的示例路径); c) 现在您的计划作业/脚本如 */10 * * * * sh runMyJob.sh &; d) 从 crontab 中删除 echo $PATH,因为它现在不需要。
在您的 cron 中设置所需的 PATH
crontab -e
编辑:按 i
PATH=/usr/local/bin:/usr/local/:or_whatever
10 * * * * your_command
保存并退出 :wq
i
”的说明和如何退出的指导假定读者是 vi
受害者。更好的解决方案可能是将 VISUAL
设置为您在 shell 配置中熟悉和熟悉的编辑器的路径,例如 export VISUAL=/usr/bin/emacsclient
我知道这已经得到了回答,但我认为他对某些人会有用。我最近解决了一个类似的问题 (found here),以下是我为回答这个问题所采取的步骤的重点:
确保您在 PYTHONPATH 中拥有所需的变量(可在此处和此处找到,并在此处获取更多信息)内的 .profile 或 .bash_profile 用于您想要测试脚本以确保其正常工作的任何 shell。编辑您的 crontab 以包含在 cron 作业中运行脚本所需的目录(在此处和此处找到) a) 确保在 PATH 变量 (.) 中包含根目录,如此处所述(基本上,如果您正在运行一个可执行文件您的命令需要能够找到根目录或存储可执行文件的目录)以及可能在您的 crontab 文件中的这些(/sbin:/bin:/usr/sbin:/usr/bin),创建一个将更改的 cronjob目录到您之前成功运行脚本的目录(即 Users/user/Documents/foo) a) 这将如下所示: * * * * cd /Users/user/Documents/foo; bar -l doSomething -v
如果您使用 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
/etc/crontab
中设置的所有路径都可用于 cron。 (sudo crontab -e
)