我正在尝试从cron运行Django管理命令。我使用virtualenv保持我的项目沙盒。

我在这里和其他地方看到了从virtualenv中运行管理命令的示例,例如:

0 3 * * * source /home/user/project/env/bin/activate && /home/user/project/manage.py command arg

然而,尽管syslog显示了任务应该在何时启动的条目,但该任务从未实际运行(脚本的日志文件为空)。如果我从shell中手动运行这一行,它将按预期工作。

我目前可以通过cron运行命令的唯一方法是将命令分解并将它们放在一个哑bash包装脚本中:

#!/bin/sh
source /home/user/project/env/bin/activate
cd /home/user/project/
./manage.py command arg

编辑:

Ars提出了一个命令的工作组合:

0 3 * * * cd /home/user/project && /home/user/project/env/bin/python /home/user/project/manage.py command arg

至少在我的例子中,调用virtualenv的激活脚本没有任何作用。这招管用,所以节目继续。


当前回答

如果你和我一样是MacOS用户,你可以在/var/mail/{username}文件中查看crontab错误信息。像这样

tail /var/mail/{username}

如果出现“操作不允许”错误,也许你必须将cron添加到全磁盘访问应用程序(安全和隐私>隐私>全磁盘访问应用程序/execs)。

点击+按钮,转到/usr/sbin,双击cron文件。 然后它将修复“不允许”错误。详细步骤

这是我的代码:

0 19 * * * cd /Users/user/Desktop/Project && source /Users/user/Desktop/Project/venv/bin/activate && python command arg

其他回答

这是一种保持crontab命令与常规命令非常相似的简单方法(在Ubuntu 18.04中进行了测试)。一些需要记住的关键注意事项:

你可以使用。命令,而不是源。(crontab默认使用sh,而不是bash,因此它没有source。) ~和$变量在crontab命令中展开。(只有crontab环境语句不进行变量展开。)

这里有一些例子,如果你有一个文件~/myproject/main.py:

* * * * * cd ~/myproject && . .venv/bin/activate && python main.py > /tmp/out1 2>&1

您也可以直接调用venv目录中python的特定路径,然后不需要调用activate。

* * * * * ~/myproject/.venv/bin/python ~/myproject/main.py > /tmp/out2 2>&1

这样做的缺点是您需要指定两次项目路径,这使得维护更加棘手。为了避免这种情况,你可以使用一个shell变量,这样你只指定一次项目路径:

* * * * * project_dir=~/myproject ; $project_dir/.venv/bin/python $project_dir/main.py > /tmp/out3 2>&1

如果你在使用python,并且使用Conda虚拟环境,其中你的python脚本包含shebang #!/usr/bin/env python:

* * * * * cd /home/user/project && /home/user/anaconda3/envs/envname/bin/python script.py 2>&1

此外,如果你想在你的脚本中捕获任何输出(例如打印,错误等),你可以使用以下命令:

* * * * * cd /home/user/project && /home/user/anaconda3/envs/envname/bin/python script.py >> /home/user/folder/script_name.log 2>&1

不用再看了:

0 3 * * * /usr/bin/env bash -c 'cd /home/user/project && source /home/user/project/env/bin/activate && ./manage.py command arg' > /dev/null 2>&1

通用的方法:

* * * * * /usr/bin/env bash -c 'YOUR_COMMAND_HERE' > /dev/null 2>&1

这样做的好处是您不需要将crontab的SHELL变量从sh更改为bash

在使用virtualenv时,运行python cron作业的唯一正确方法是激活环境,然后执行环境的python来运行代码。

一种方法是在你的python脚本中使用virtualenv的activate_this,参见:http://virtualenv.readthedocs.org/en/latest/userguide.html#using-virtualenv-without-bin-python

另一种解决方案是回显完整的命令,包括激活环境并将其管道到/bin/bash.考虑一下你的/etc/crontab:

***** root echo 'source /env/bin/activate; python /your/script' | /bin/bash

与其在虚拟环境特定的shebangs上瞎折腾,还不如在crontab上预先加上PATH。

在激活的virtualenv中,运行这三个命令,python脚本就可以工作了:

$ echo "PATH=$PATH" > myserver.cron
$ crontab -l >> myserver.cron
$ crontab myserver.cron

crontab的第一行现在应该是这样的:

PATH=/home/me/virtualenv/bin:/usr/bin:/bin:  # [etc...]