如何让 CRON 调用正确的路径
Posted
技术标签:
【中文标题】如何让 CRON 调用正确的路径【英文标题】:How to get CRON to call in the correct PATHs 【发布时间】:2011-01-24 04:34:12 【问题描述】:我正在尝试让 cron 调用正确的路径。当我从 shell 运行 Python 脚本时,脚本运行良好,因为它使用 bashrc 中设置的 PATH,但是当我使用 cron 时,所有 PATH 都没有从 bashrc 中使用。是否有一个文件我可以为 cron 输入路径(如 bashrc)或从 bashrc 调用路径的方法?
抱歉,我认为我的措辞不正确,我可以运行正确的脚本(这意味着 crontab 中脚本的 PATH 不是问题),只是当该脚本运行时我运行构建并这使用在.bashrc
中设置的路径。当我登录后运行脚本时,.bashrc
路径被拉入。由于 cron 没有在 shell 中运行,因此它不会拉入.bashrc
。有没有一种方法可以在无需编写 bash 脚本包装器的情况下实现这一点?
【问题讨论】:
还可以看看这里给出的关于如何让 bashrc 设置适用于 cronjobs 的建议:***.com/q/15557777/1025391 将您的个人资料包含在当前环境中的神奇、简单且正确的命令是source /etc/profile
,它应该吃掉.bashrc
以及许多其他可能为您丢失的东西。如果您希望某些脚本“独立”运行,显式配置文件来源会非常有用,它还可以防止奇怪的环境等等......
@exa +100 这使得 crontab 调用的sh
脚本工作。您可以通过添加类似* * * * * echo $PATH > ~/crontab_path.txt
的作业并在一分钟后检查文件来确认它是否更新了路径。
【参考方案1】:
使用正确的值将 PATH 定义添加到用户 crontab 将有助于... 我已经在顶部填充了这条线(在 cmets 之后,在 cron 作业之前):
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
这足以让我的所有脚本正常工作...如果需要,请在其中包含任何自定义路径。
【讨论】:
对于用户 crontab,这应该是正确的答案。并非系统上的每个人都可以编辑/etc/crontab
。这是用户级别上最简单的答案。干得好@Treviño。如果您同意,请投票。【参考方案2】:
我发现的最简单的解决方法如下:
* * * * * root su -l -c command
此示例以 root 用户身份调用 su
并使用用户的完整环境(包括 $PATH)启动 shell,就像他们已登录一样设置。它在不同发行版上的工作方式相同,比采购 .bashrc 更可靠(这对我不起作用)并避免硬编码特定路径,如果您提供示例或设置工具并且不知道用户系统上的发行版或文件布局,这可能是一个问题。
你也可以在su
之后指定用户名,如果你想要一个不同于root的用户,但你可能应该在su
命令之前留下root
参数,因为这样可以确保su
有足够的权限切换到任何您指定的用户。
【讨论】:
【参考方案3】:我使用了/etc/crontab
。我使用了vi
并在我需要的路径中输入了这个文件并以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
【讨论】:
这在用户级别与 crontab -e 一起使用,这样也更安全。 我可以用 bash 代替 sh 吗? 奇怪的是(对我来说)@chrissygormley 显示的 /etc/crontab 中设置的默认 PATH 以及我的(Ubuntu)crontab 中设置的默认路径与 /etc/ 中的路径不同环境,特别是它把 /sbin 和 /bin 放在 /usr/sbin 和 /usr/bin 之前。我现在在我的 /etc/crontab 中更改了它,使其与用户环境相同。 不适合我..我正在将 cron 内容输出到文件中。 Cron 运行,文件创建,但它没有在其中放入任何内容。 在 Ubuntu 14.04 中以 root 身份运行时,似乎并非所有/etc/crontab
中设置的路径都可用于 cron。 (sudo crontab -e
)【参考方案4】:
如果您使用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
【讨论】:
【参考方案5】:在我的 crontab 中的命令行之前设置 PATH 对我有用:
* * * * * PATH=$PATH:/usr/local/bin:/path/to/some/thing
【讨论】:
更喜欢这种方式。或指定脚本的完整路径。 我不认为路径会继续增长,每次运行都会是一个新环境,带有一个新的 PATH 副本...... 可以确认@jjcf89 是正确的,PATH 每次运行都是新鲜的。【参考方案6】:在你的 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
【参考方案7】:
@Trevino:您的回答帮助我解决了我的问题。但是,对于初学者来说,尝试给出一步一步的方法。
-
通过
$ echo $JAVA_HOME
获取您当前的java安装
$ crontab -e
* * * * * echo $PATH
- 这让您了解 crontab 目前使用的 PATH 值是什么。运行 crontab 并获取 crontab 使用的 $PATH 值。
现在再次编辑 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
,因为它现在不需要。
【讨论】:
【参考方案8】:让你的变量为你工作,这将允许访问 t
在 /etc/profile.d/*.sh 中定义您的 PATH
System-wide environment variables
/etc/profile.d 目录中带有 .sh 扩展名的文件会在每次进入 bash 登录 shell 时执行(例如,从控制台或通过 ssh 登录时),以及在桌面会话时由 DisplayManager 执行加载。
例如,您可以创建文件 /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
【讨论】:
【参考方案9】:问题
您的脚本在您从控制台运行时可以运行,但在 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
样本输出
【讨论】:
请don’t post images of code or error messages.【参考方案10】:如果您不想在不同的地方进行相同的编辑,那么大致这样做:
* * * * * . /home/username/.bashrc && yourcommand all of your args
.空间,然后是 .bashrc 的路径和 && 命令是让你的环境更改到正在运行的 bash shell 中的魔法。同样,如果你真的希望 shell 是 bash,最好在你的 crontab 中有一行:
SHELL=/bin/bash
希望它对某人有所帮助!
【讨论】:
【参考方案11】:我知道这已经得到了回答,但我认为他对某些人会有用。我最近解决了一个类似的问题 (found here),以下是我为回答这个问题所采取的步骤的重点:
-
1234563 .
编辑您的 crontab 以包含在 cron 作业中运行脚本所需的目录(可在此处和此处找到)
a) 确保在 PATH 变量 (.) 中包含根目录,如此处所述(基本上,如果您使用命令运行可执行文件,它需要能够找到根目录或存储可执行文件的目录)可能还有这些 (/sbin:/bin:/usr/sbin:/usr/bin)
在您的 crontab 文件中,创建一个 cronjob,将目录更改为您之前成功运行脚本的目录(即 Users/user/Documents/foo)
a) 这将如下所示:
* * * * cd /Users/user/Documents/foo; bar -l doSomething -v
【讨论】:
【参考方案12】:在我的 AIX cron 上,它从 /etc/environment 获取它的环境变量,而忽略 .profile 中设置的内容。
编辑:我还检查了几个不同年龄的 Linux 机器,它们似乎也有这个文件,所以这可能不是 AIX 特定的。
我使用 joemaller 的 cron 建议检查了这一点,并在 /etc/environment 中编辑 PATH 变量之前和之后检查了输出。
【讨论】:
【参考方案13】:很可能,cron 运行在一个非常稀疏的环境中。检查 cron 使用的环境变量,方法是附加一个将env
转储到如下文件的虚拟作业:
* * * * * env > env_dump.txt
将其与普通 shell 会话中 env
的输出进行比较。
您可以通过在 crontab 顶部定义自己的环境变量来将它们添加到本地 crontab。
下面是在当前 crontab 前添加 $PATH
的快速修复:
# echo PATH=$PATH > tmp.cron
# echo >> tmp.cron
# crontab -l >> tmp.cron
# crontab tmp.cron
生成的 crontab 看起来与 chrissygormley 的答案相似,PATH 定义在 crontab 规则之前。
【讨论】:
【参考方案14】:您应该将完整路径放入您的crontab
。这是最安全的选择。
如果您不想这样做,可以在程序周围放置一个包装脚本,并在其中设置 PATH。
例如
01 01 * * * command
变成:
01 01 * * * /full/path/to/command
此外,从cron
调用的任何程序都应该非常小心它运行的程序,并可能为PATH
变量设置自己的选择。
编辑:
如果你不知道命令在哪里,你想从你的 shell 中执行 which <command>
,它会告诉你路径。
EDIT2:
因此,一旦您的程序运行,它应该做的第一件事是将 PATH
和任何其他必需的变量(例如 LD_LIBRARY_PATH
)设置为脚本运行所需的值。
基本上不是考虑如何修改 cron 环境以使其更适合您的程序/脚本 - 让您的脚本在启动时设置一个适当的环境来处理它给定的环境。
【讨论】:
如果它在你的路径中使用'which command',它会给你完整的路径 @Douglas Leeder -- 当您说将完整路径放入 cron 时,您的意思是将其放入 crontab 或其他文件中吗?如果 cron 命令是:'01 01 * * * command',你会怎么做。谢谢 @chrissygormley - 是的crontab
。
抱歉,一定是有些混乱。我已经改写了上面的问题。
您应该更喜欢type
和/或command
而不是which
和whereis
等非标准实用程序。有时它们存在并起作用,有时它们不存在。【参考方案15】:
cron 作业的默认环境非常稀疏,可能与您开发 python 脚本的环境有很大不同。对于可能在 cron 中运行的脚本,您所依赖的任何环境都应该明确设置。在 cron 文件本身中,包含 python 可执行文件和 python 脚本的完整路径。
【讨论】:
以上是关于如何让 CRON 调用正确的路径的主要内容,如果未能解决你的问题,请参考以下文章
如何让 perl 正确传递具有多个参数和复杂文件路径(空格和符号)的命令行参数?