如何让CRON调用正确的PATH


124

我试图让cron调用正确的PATH。当我从外壳运行Python脚本时,脚本运行良好,因为它使用了bashrc中设置的PATH,但是当我使用cron时,bashrc中并未使用所有PATH。是否有一个文件可以像bashrc一样输入cron的PATH或从bashrc调用PATH的方法?

抱歉,我的措词不正确,我可以运行正确的脚本(这意味着crontab中脚本的PATH不是这里的问题),只是该脚本在运行时,我运行了构建,并且使用了在中设置的路径.bashrc。登录后运行脚本时,将.bashrc拉入PATH。由于cron并未在shell中运行,所以说它不会拉入.bashrc。有没有一种方法可以不必编写bash脚本包装器而将其引入?


也可以看看这里给出的关于如何使bashrc设置适用于cronjobs的建议:stackoverflow.com/q/15557777/1025391
moooeeeep

2
将您的个人资料包含在当前环境中的神奇,简单且正确的命令是source /etc/profile,它应该会给.bashrc您带来麻烦,并给您带来很多其他可能丢失的东西。如果您希望某些脚本“独立运行”,则明确的配置文件来源非常有用,它还可以防止怪异的环境,等等……
exa 2014年

1
@exa +100这使shcrontab调用的脚本起作用。您可以通过添加作业(例如* * * * * echo $PATH > ~/crontab_path.txt,一分钟后检查文件)来确认它更新了路径。
geotheory,2015年

Answers:


177

我用过/etc/crontab。我使用vi并在该文件中输入了所需的PATH,然后以root身份运行了它。普通的crontab会覆盖您设置的PATH。关于如何执行此操作的很好的教程

系统范围的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

17
这可以在用户级别与crontab -e一起使用,并且这样做也更安全。
罗伯特·布里斯塔

2
我可以使用bash代替sh吗?
2013年

1
对我来说,奇怪的是,在/ etc / crontab中设置的默认路径(如@chrissygormley所示)以及在我的(Ubuntu)crontab中设置的默认路径与/ etc / environment中的路径不同,特别是将/ sbin和/ bin位于/ usr / sbin和/ usr / bin之前。现在,我已经在/ etc / crontab中对此进行了更改,使其与用户环境相同。
scoobydoo 2015年

对我不起作用..我正在将cron内容输出到文件中。Cron运行,创建文件,但未在其中添加任何内容。
Volatil3,2015年

2
/etc/crontab在Ubuntu 14.04中以root身份运行时,似乎并非所有设置的路径都对cron可用。(sudo crontab -e
大卫·奥利佛

50

cron很可能在非常稀疏的环境中运行。通过添加一个虚拟作业来检查cron使用的环境变量,该虚拟作业将转储env到以下文件中:

* * * * * env > env_dump.txt

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

您可以通过在crontab的顶部定义自己的环境变量到本地crontab。

这是$PATH在当前crontab之前添加的快速修复程序:

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

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


22

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

例如

01 01 * * * command

变成:

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

同样,调用from的任何东西都cron应该对它运行的程序非常小心,并可能为PATH变量设置自己的选择。

编辑:

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

编辑2:

因此,一旦程序运行,便应将其要做的第一件事设置为PATH,将所有其他必需的变量(例如LD_LIBRARY_PATH)设置为脚本运行所需的值。
基本上,不用思考如何修改cron环境以使其更适合您的程序/脚本,而是通过在启动时设置适当的脚本来使脚本处理给定的环境。


1
如果它在您的路径中使用“哪条命令”,它将为您提供完整的路径
Paul Whelan 2010年

@Douglas Leeder-当您说将完整路径放入cron时,是指将其放入crontab或另一个文件中吗?如果是cron命令,则如何处理:'01 01 * * * command'。谢谢
chrissygormley

@chrissygormley-是的crontab
Douglas Leeder

抱歉,一定会有一些混乱。我已经改写了上面的问题。
chrissygormley,2010年

16

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

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

喜欢这种方式。或指定脚本的完整路径。
zw963 '17

5
我认为这条路不会持续增长,每次运行都会是一个新环境,并带有PATH的新副本...
jjcf89

可以确认@ jjcf89是正确的,每次运行时PATH都是新鲜的。
electrovir

14

使用正确的值向用户crontab中添加PATH定义将有帮助...我只用以下方法填充了我的内容:

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

这足以使我的所有脚本正常工作...如果需要,请在此包括任何自定义路径。


1
对于crontab用户,这应该是正确的答案。不是系统上的每个人都可以编辑/etc/crontab。这是在用户级别上最简单的答案。干得好@Treviño。如果您同意,请对此投票。
frederickjh

14

让您的变量为您工作,这将允许访问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运行脚本或命令

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

11

问题

当您从控制台运行脚本时,该脚本可以运行,但在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示例输出


3

在我的AIX cron上,它忽略了/ profile / environment中的环境变量,而忽略了.profile中的设置。

编辑:我还签出了几个不同年龄的Linux盒子,这些盒子似乎也有这个文件,因此这可能不是特定于AIX的。

我使用joemaller的cron建议检查了此内容,并在/ etc / environment中编辑PATH变量之前和之后检查了输出。


3

如果您不想在各个地方进行相同的编辑,请大致执行以下操作:

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

的。空格,然后是.bashrc的路径以及&&命令,是将环境更改为正在运行的bash shell的神奇之处。同样,如果您真的希望shell成为bash,则在crontab中插入一行是一个好主意:

SHELL=/bin/bash

希望它能对某人有所帮助!


2

cron作业的默认环境非常稀疏,可能与您在其中开发python脚本的环境非常不同。对于可能在cron中运行的脚本,应明确设置您依赖的任何环境。在cron文件本身中,包括python可执行文件和python脚本的完整路径。


2

我知道已经回答了,但是我认为他对某些人有用。我最近解决了一个类似的问题(在此处找到),这是我回答这个问题的步骤的重点:

  1. 确保在.profile或.bash_profile内的PYTHONPATH中(在此处和此处以及有关更多信息)具有所需的变量,以供要测试脚本以确保其工作的任何shell使用。

  2. 编辑您的crontab,以将在cron作业中运行脚本所需的目录包括在内(此处和此处)

    a)确保按如下说明在PATH变量(。)中包含根目录(基本上,如果您正在使用命令运行可执行文件,则它必须能够找到根目录或存储可执行文件的目录),并且可能(/ sbin:/ bin:/ usr / sbin:/ usr / bin)

  3. 在您的crontab文件中,创建一个cronjob,它将目录更改为您之前成功运行脚本的目录(即Users / user / Documents / foo)

    a)如下所示:

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

2

@Trevino:您的回答帮助我解决了我的问题。但是,对于初学者而言,请尝试逐步解决问题。

  1. 通过获取当前的Java安装 $ echo $JAVA_HOME
  2. $ crontab -e
  3. * * * * * echo $PATH-这可以让您了解crontab当前正在使用的PATH值。运行crontab并获取crontab使用的$ PATH值。
  4. 现在编辑的crontab重新设置你的Java bin路径:1)crontab -e; b)PATH=<value of $JAVA_HOME>/bin:/usr/bin:/bin(其示例路径);c)现在您的预定工作/脚本如下*/10 * * * * sh runMyJob.sh &;d)echo $PATH从crontab中删除,因为现在不需要了。


1

我找到的最简单的解决方法如下所示:

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

这个例子调用 su以root用户身份,并使用用户的完整环境(包括$ PATH)启动外壳程序,将其设置为好像已登录一样。它在不同发行版上的工作方式相同,比采购.bashrc(对于我),并避免对特定路径进行硬编码,如果您要提供示例或设置工具并且不知道用户系统上的发行版或文件布局,则可能会出现问题。

su如果您想要的用户名不同于root用户,也可以在之后指定用户名,但是您应该rootsu命令前保留参数,因为这样可以确保su有足够的特权切换到您指定的任何用户。


-3

您应该使用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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.