我正在尝试从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的激活脚本没有任何作用。这招管用,所以节目继续。
对我来说,最好的解决办法是两者兼得
使用venv bin/目录下的python二进制文件
设置python路径
要包含venv模块目录。
man python提到在shell中修改路径$PYTHONPATH或在python中修改sys.path
其他回答提到了使用shell来实现这一点的想法。从python中,向我的脚本中添加以下行可以让我成功地直接从cron运行它。
import sys
sys.path.insert(0,'/path/to/venv/lib/python3.3/site-packages');
这是它在互动会话中的样子
Python 3.3.2+ (default, Feb 28 2014, 00:52:16)
[GCC 4.8.1] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path
['', '/usr/lib/python3.3', '/usr/lib/python3.3/plat-x86_64-linux-gnu', '/usr/lib/python3.3/lib-dynload']
>>> import requests
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named 'requests'
>>> sys.path.insert(0,'/path/to/venv/modules/');
>>> import requests
>>>
我也遇到过同样的问题,并花了很多时间去解决它。
这里没有一个解决方案对我有帮助,所以我分享了对我有用的方法:
在项目目录中打开一个新文件“pick_name.sh”。
在"pick_name.sh"文件中,写入并保存以下代码行:
#!/bin/bash
source /YOUR_VIRTUAL_ENV_PATH/bin/activate
export PYTHONPATH="${PYTHONPATH}:/PATH_TO_CUSTOM_MODULE_YOU_CREATED**OPTIONAL**"
export PYTHONPATH="${PYTHONPATH}:/PATH_TO_ANOTHER_CUSTOM_MODULE_YOU_CREATED**OPTIONAL**"
cd /PATH_TO_DIR_STORING_FILE_NAME.PY
python file_name.py
转到/var/spool/cron/crontabs(或到您的cron管理文件所在的位置)并打开“根”文件。
将这些行添加到crontab文件夹中的根文件中:
# m h dom mon dow command
* * * * * /PATH_TO_DIR_WHERE_PICK_NAME.SH_SITS/pick_name.sh >> /YOUR_PROJECT_DIR/cron_output.txt 2>&1
注:
This command (section 4.) will run the "pick_name.sh" file.
In this example it runs every minute, so make sure you change it according to your needs.
It writes all logs to a log file called "cron_ouput".
No need to create the file before, it will be created automatically.
Make sure to replace all paths (I wrote them in capital letters) to your paths.
You can change file names, if so, make sure to change it in all appearances in my instructions to avoid errors.
If you want to add another py file to run by cron, you need to add it to the "pick_nam.sh" file* not to the cron. Simply duplicate section 2. lines in the "pick_nam.sh" but without the "#!/bin/bash" part.
Then, every time the cron will run "pick_name.sh" it will run all the files you specified inside of it.
Make sure to restart cron after changes, it could have saved me a lot of debugging time, use this command:
systemctl restart cron
我已经在我的Django项目中添加了下面的脚本manage.sh,它获取了virtualenv,然后运行manage.py脚本,不管你传递给它什么参数。它使得在virtualenv (cron, systemd单元,基本上任何地方)中运行命令变得非常容易:
#! /bin/bash
# this is a convenience script that first sources the venv (assumed to be in
# ../venv) and then executes manage.py with whatever arguments you supply the
# script with. this is useful if you need to execute the manage.py from
# somewhere where the venv isn't sourced (e.g. system scripts)
# get the script's location
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
# source venv <- UPDATE THE PATH HERE WITH YOUR VENV's PATH
source $DIR/../venv/bin/activate
# run manage.py script
$DIR/manage.py "$@"
然后在你的cron条目中运行:
0 3 * * * /home/user/project/manage.sh command arg
只需记住,您需要使manage.sh脚本可执行