我建议创建一个使用 cron 运行的 management command。
使用此方法,您可以使用完整的 Django ORM、所有方法等。将您的脚本包装在 try/except 中,您可以选择以任何您希望的方式记录故障 - 电子邮件通知、外部日志系统(如 Sentry)、直接记录到数据库等。
我使用 supervisord 来运行 cron,它运行良好。它依赖于久经考验的工具,不会让您失望。
最后,使用数据库单例来跟踪批处理作业是否已运行或当前正在运行的环境中运行多个 Django 实例并以负载平衡方式运行,这不是一个坏做法,即使您感觉有点讨厌它。 DB 是一种非常可靠的方法,可以告诉您 DB 是否正在处理中。
关于 cron 的一件烦人的事情是它不会导入 Django 可能需要的环境变量。我用一个简单的 Python 脚本解决了这个问题。
它会在启动时写入包含所需环境变量等的 crontab。此示例适用于 EBS 上的 Ubuntu,但应该是相关的。
#!/usr/bin/env python
# run-cron.py
# sets environment variable crontab fragments and runs cron
import os
from subprocess import call
from master.settings import IS_AWS
# read django's needed environment variables and set them in the appropriate crontab fragment
eRDS_HOSTNAME = os.environ["RDS_HOSTNAME"]
eRDS_DB_NAME = os.environ["RDS_DB_NAME"]
eRDS_PASSWORD = os.environ["RDS_PASSWORD"]
eRDS_USERNAME = os.environ["RDS_USERNAME"]
try:
eAWS_STAGING = os.environ["AWS_STAGING"]
except KeyError:
eAWS_STAGING = None
try:
eAWS_PRODUCTION = os.environ["AWS_PRODUCTION"]
except KeyError:
eAWS_PRODUCTION = None
eRDS_PORT = os.environ["RDS_PORT"]
if IS_AWS:
fto = '/etc/cron.d/stortrac-cron'
else:
fto = 'test_cron_file'
with open(fto,'w+') as file:
file.write('# Auto-generated cron tab that imports needed variables and runs a python script')
file.write('\nRDS_HOSTNAME=')
file.write(eRDS_HOSTNAME)
file.write('\nRDS_DB_NAME=')
file.write(eRDS_DB_NAME)
file.write('\nRDS_PASSWORD=')
file.write(eRDS_PASSWORD)
file.write('\nRDS_USERNAME=')
file.write(eRDS_USERNAME)
file.write('\nRDS_PORT=')
file.write(eRDS_PORT)
if eAWS_STAGING is not None:
file.write('\nAWS_STAGING=')
file.write(eAWS_STAGING)
if eAWS_PRODUCTION is not None:
file.write('\nAWS_PRODUCTION=')
file.write(eAWS_PRODUCTION)
file.write('\n')
# Process queue of gobs
file.write('\n*/8 * * * * root python /code/app/manage.py queue --process-queue')
# Every 5 minutes, double-check thing is done
file.write('\n*/5 * * * * root python /code/app/manage.py thing --done')
# Every 4 hours, do this
file.write('\n8 */4 * * * root python /code/app/manage.py process_this')
# etc.
file.write('\n3 */4 * * * root python /ode/app/manage.py etc --silent')
file.write('\n\n')
if IS_AWS:
args = ["cron","-f"]
call(args)
在 supervisord.conf 中:
[program:cron]
command = python /my/directory/runcron.py
autostart = true
autorestart = false