我正在尝试从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的激活脚本没有任何作用。这招管用,所以节目继续。


当前回答

我也遇到过同样的问题,并花了很多时间去解决它。 这里没有一个解决方案对我有帮助,所以我分享了对我有用的方法:

在项目目录中打开一个新文件“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

其他回答

我想添加这一点,因为我花了一些时间解决这个问题,并没有在这里找到一个答案,在cron和virtualenv中使用变量的组合。也许能帮到别人。

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DIR_SMTH="cd /smth"
VENV=". venv/bin/activate"
CMD="some_python_bin do_something"
# m h  dom mon dow   command
0 * * * * $DIR_SMTH && $VENV && $CMD -k2 some_target >> /tmp/crontest.log 2>&1

当它被配置成

生下来的微片venv / bin / sh activate。”

感谢@davidwinterbottom, @reed-sandberg和@mkb给出了正确的方向。接受的答案实际上工作得很好,直到你的python需要运行一个脚本,必须从venv/bin目录运行另一个python二进制文件。

与其在虚拟环境特定的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...]

这是一种保持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

我也遇到过同样的问题,并花了很多时间去解决它。 这里没有一个解决方案对我有帮助,所以我分享了对我有用的方法:

在项目目录中打开一个新文件“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

你应该能够通过在虚拟环境中使用python来做到这一点:

/home/my/virtual/bin/python /home/my/project/manage.py command arg

编辑:如果你的django项目不在PYTHONPATH目录下,那么你需要切换到正确的目录:

cd /home/my/project && /home/my/virtual/bin/python ...

您也可以尝试从cron记录失败:

cd /home/my/project && /home/my/virtual/bin/python /home/my/project/manage.py > /tmp/cronlog.txt 2>&1

另一件要尝试的事情是在你的manage.py脚本最上面做同样的改变:

#!/home/my/virtual/bin/python