Crontab无法执行Python脚本?

62

我的 Python 脚本在 crontab 下没有运行。

我已经在 Python 脚本的顶部添加了以下内容:

#!/usr/bin/python

我已经尝试了这个:

chmod a+x myscript.py

我添加到了我的crontab -e

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=""

* * * * * /home/me/project/myscript.py
我的 /var/log/cron 文件显示:
Sep 21 11:53:02 163-dhcp /USR/SBIN/CROND[2489]: (me) CMD (/home/me/project/myscript.py)

但是我的脚本没有运行,因为当我检查我的SQL数据库时,没有任何变化。如果我直接在终端中运行:

python /home/me/project/myscript.py

我得到了正确的结果。

这是myscript.py

#!/usr/bin/python

import sqlite3

def main():
    con = sqlite3.connect("test.db")

    with con:

        cur = con.cursor()

        cur.execute("CREATE TABLE IF NOT EXISTS testtable(Id INTEGER PRIMARY KEY, Name TEXT)")

        cur.execute("INSERT INTO testtable(Name) VALUES ('BoB')")

        cur.execute("SELECT * FROM testtable")

        print cur.fetchall()    

if __name__ == "__main__":
    main()

根据评论:是的,/usr/bin/python 存在。 我也可以直接使用 /home/me/project/myscript.py 运行 python 脚本。 /usr/bin/python /home/me/project/myscript.py 可以工作。 所以我不相信这是原因?


脚本里面有什么?它是否依赖于任何环境因素? - tMC
是的,我认为我们需要查看你的myscript.py文件内部。 - Scott Presnell
2
将MAILTO变量设置为您的用户名。然后您将在邮件中收到一些错误消息,这可能会提供一些线索。 - unutbu
3
您还可以验证直接使用/home/me/project/myscript.py运行它是否有效(不需要在开头加上python,因为它是通过cron运行的)。 - Danica
1
test.db 文件在你的主目录里还是其他地方?cron 任务是从你的主目录运行的,所以你可能需要更改目录或使用完整路径名来定位数据库。 - twalberg
显示剩余2条评论
15个回答

63

在互联网上有很多不完整的答案,因此我想记录下来以节省其他人的时间。

首先,cronjob没有很好地告诉您它失败的原因。我建议将stderr输出发送到日志文件中,像这样:

Crontab命令:

# m h  dom mon dow   command
* * * * * /path/to/your_file.sh >> out.txt  2>&1

由于很可能是以用户身份运行命令,请检查日志文件的主目录。请注意,此脚本每分钟运行一次,非常适合调试。

下一个问题可能是您的路径问题...因为脚本很可能正在尝试从您的主目录中执行。此脚本设置当前目录,将其输出到文件中,然后运行您的程序。

请尝试以下操作:

脚本文件

#!/bin/sh
cd "$(dirname "$0")";
CWD="$(pwd)"
echo $CWD
python your_python_file.py

希望这篇文章能够帮助其他人节省一些调试时间!!!


4
谢谢!你帮我省了很多调试时间!!! 我一直在遇到一个随机不运行的cron问题,这真是噩梦。 - Richard
2
最后一部分的“2>&1”是什么意思? - Nechadil
1
我和@Nechadil有同样的问题,2>&1是什么意思?先谢谢了! - EnriqueBet
3
@EnriqueBet,我后来找到了答案。请查看此链接 :) https://unix.stackexchange.com/questions/99263/what-does-21-in-this-command-mean - Nechadil
1
感谢 @Nechadil! - EnriqueBet
显示剩余5条评论

45

当您在shell中键入/home/me/project/myscript.py时,会发生什么?

您能否在crontab命令中明确使用/usr/bin/python

您可以使用test.db的绝对路径或cd到正确的目录,然后执行您的Python脚本吗?

这有助于在Python中编写调试语句并记录一些数据。Crontab很难进行调试。


5
哈哈,你做到了!我已经将test.db更改为绝对路径/home/me/project/test.db ... 而且它起作用了! - user1636922
cron作业运行在/home/me,显然您想象它会运行在/home/me/project。只要您理解(相对路径和)cron启动作业的位置,就不需要绝对路径。 - tripleee

19
通常这是由于crontab使用的Python版本与您在shell中使用的版本不同造成的。 解决方法如下:
  1. 获取您在shell中使用的Python版本:

$ which python # 可能是"python3"或其他 /usr/bin/python

  1. 在crontab文件中使用特定的Python版本:

* * * * * /usr/bin/python test.py

另外,还要提到在shell中使用env -i /bin/bash --noprofile --norc可以让您拥有与crontab使用的相同环境,这对于调试非常有帮助。

非常感谢您提供的env命令。它帮助我解决了我的问题! - Ken Harris

19

可能由于无法找到Python解释器,脚本无法启动。Crontab环境可能与您正在使用的shell环境非常不同,搜索路径可能会有很大的差异。

同时,您可以通过显式地启动Python解释器来测试脚本,而您希望Crontab仅启动脚本。

我将以下行放在我的Python脚本顶部:

\#!/bin/env python

这行代码将有助于定位解释器,不管它安装在哪个目录中,只要它在搜索路径中即可。


我目前在bash中,我已经添加了你的建议 #!/bin/env python。看起来它没有起作用。 - user1636922
首先,查看您是否有/bin/env或者env是否在不同的目录中。 - shargors
67
输入以下命令,以获得与crontab使用的相同环境: env -i /bin/bash --noprofile --norc 接下来启动您的Python脚本并查看其失败的原因。这应该能给您一个想法。 - shargors
11
@shargors,我无法形容你的评论对我有多大帮助。在我看来,你的评论应该被接受为答案:Python脚本在原始问题中失败的具体原因并不像解决环境问题的一般方法那样重要。谢谢! :) - Andres F.
@shargors 你可能想在答案下面添加你的评论。虽然它不是 OP 的问题的“答案”,但它似乎已经帮助了很多人(包括我)。 - eDonkey

9
通常,像这样的crontab问题是由于PATH环境变量比您正常用户的PATH环境更加严格/不同所致。由于您的shell使用PATH环境变量来查找可执行文件(例如,当您在shell提示符下键入“python”时,在/usr/bin中找到/usr/bin/python),因此当PATH缺失常见位置(例如/usr/bin或/usr/sbin)时,您的cron作业将失败。这已经折磨过我很多次了。简单的解决方法就是在您的crontab文件顶部明确设置PATH,然后再添加任何需要它的命令。因此,只需像往常一样编辑crontab,并在顶部添加类似以下内容的内容(如果您的二进制文件不在以下路径之一,则需要在冒号后面添加它):
PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin

或者,只需在crontab中使用您的二进制文件和脚本的绝对路径。


5

试试这个

* * * * * cd <directory_where_python_file_is> && bin/app etc/app_defaults.yaml

在cron中存在一些路径问题。因此,当您进入包含Python文件的目录时,cron会像魅力一样工作!


3
最简单的处理方法是将Python安装路径添加到脚本顶部的PATH中。类似以下内容:
#!/usr/bin/env bash
export PATH="{path to your python installation}:$PATH"
python {python_file_name}.py

如 @Shargors 所说,您可以通过以下方式进行测试:

env -i /bin/bash --noprofile --norc

3

我也遇到了同样的问题。尽管手动执行脚本可以正常工作,在crontab中却没有任何选项有效。我将脚本从/home/user/script_directory/移动到/opt/scripts/,然后它就开始正常工作了。问题可能是因为无法访问(读取)位于主目录中的子文件夹所导致的。


3
如果您使用Anaconda进行Python编程,那么需要使用的路径为:
/home/username/anaconda3/bin/python test.py

1
有时我会遇到相同的问题。无论我按照这里的建议尝试什么,都可能得不到结果。
因此,我开始编写“触发器”bash脚本,如下所示(让我们将其命名为trigger.sh):
#!/bin/bash

/full_path/python_script.py

我正在从crontab调用trigger.sh,一切都很顺利。

编辑:当然,不要忘记执行以下操作(给予权限):

$chmod +x python_script.py
$chmod +x trigger.sh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接