Django的定时任务管理应用
项目描述
django-cronman
概述
Django应用,用于在Python级别定义和管理周期性任务。
安装
django-cronman
可以使用pip
直接从PyPI安装
pip install django-cronman
您还可以安装它,以便使用Cron远程管理器,同时安装附加依赖项。
pip install django-cronman[redis]
定义一个新的cron作业
Cron作业定义受Django Admin配置的启发。要添加新作业,您必须在应用内创建cron_job.py
文件,在其中创建BaseCronJob
子类并注册它
from cronman.job import BaseCronJob, cron_job_registry
class HelloWorld(BaseCronJob):
"""Demo Cron Job class"""
def run(self):
"""Main logic"""
pass
cron_job_registry.register(HelloWorld)
Cron作业类通过名称注册(并引用),这可以在注册时自定义
cron_job_registry.register(HelloWorld, name='Hello')
还可以检索或注销一个类(例如,在测试时)
cron_job_registry.get('HelloWorld')
cron_job_registry.unregister('HelloWorld')
如果给定应用中有多个cron作业,建议创建一个包而不是单个cron_jobs
模块。每个类创建一个子模块,并在包的__init__.py
中进行导入和注册。
配置cron作业
为确保cron作业定期执行,您需要向CRON_JOBS
中添加条目。
CRON_JOBS = (
...
# (<time spec>, <job spec>)
# 'HelloWorld' will be executed a 5:15AM every day:
(' 15 5 * * *', 'HelloWorld'),
)
将CRONMAN_JOBS_MODULE
设置为指定cron作业的模块的点分路径名。记住,此模块必须有一个CRON_JOBS
属性。CRONMAN_JOBS_MODULE
默认为None
。例如
# settings_local.py
CRONMAN_JOBS_MODULE = 'app.cron_jobs.name'
运行调度器
在settings.CRONMAN_JOBS_MODULE
中定义的cron作业由cron
应用的cron_scheduler
命令启动。该命令构建一个应在当前周期(现在 +/- 1 分钟)执行的作业列表,并为每个作业创建一个新的子进程。
python manage.py cron_scheduler run
此命令应添加到运行定期任务的服务器的系统crontab中,并每2分钟执行一次。
运行单个cron作业
命令cron_worker run <job spec>
负责执行cron作业。
python manage.py cron_worker run HelloWorld
cron作业参数
cron作业类可以接受参数,这些参数作为位置或命名参数传递给run
方法。
class HelloWorld(BaseCronJob):
"""Demo Cron Job class"""
def run(self, what, sleep=None):
"""Main logic"""
print "Hello {}".format(what)
if sleep:
time.sleep(int(sleep))
...
python manage.py cron_worker run HelloWorld:world,sleep=5
参数作为字符串值传递,任何类型转换都应该在run
方法中完成。支持带有空格的引号字符串,但逗号只能用作参数分隔符。
python manage.py cron_worker run HelloWorld:"big world",sleep=5
cronman.utils
模块中存在用于提取列表和布尔值的实用函数。
配置Cronitor支持
cron_worker
命令可以在作业启动、完成或失败时通知Cronitor。要启用此功能,您必须
- 在设置中启用Cronitor支持
CRONMAN_CRONITOR_ENABLED = True
- 配置cron作业类
class HelloWorld(BaseCronJob):
"""Demo Cron Job class"""
cronitor_id = 'ab12z' # ID is assigned in Cronitor's dashboard
我们可以通过设置cronitor_ping_run = False
或cronitor_ping_fail = False
来禁用在cron作业启动时发送可选的"RUN"和"FAIL"ping,但这似乎不是必要的。
重要提示:当在Cronitor仪表板上添加新的监控时,请使用类型heartbeat。避免使用cron job监控,因为它们会发送假阳性警报“未按计划运行”。
配置锁
任务可以获取锁以防止并发调用。锁的形式是位于settings.CRONMAN_DATA_DIR
的PIDfiles。要为给定的cron作业类修改锁的行为,可以设置lock_type
属性。
from cronman.taxonomies import LockType
class HelloWorld(BaseCronJob):
"""Demo Cron Job class"""
lock_type = LockType.PARAMS
支持以下值:
None
- 没有锁,允许并发LockType.CLASS
(默认)- 同时只能运行给定cron作业类的一个实例(例如,Foo:p=1
和Foo:p=2
不能并发运行)LockType.PARAMS
- 同时只能运行一个类和参数的组合(例如,Foo:p=1
和Foo:p=2
可以并发运行,但对另一个Foo:p=1
的调用将被禁止)。由cron_worker
命令获取和释放锁。
我们可以为几个cron作业类配置共享锁,以确保其中只有一个在运行。
from cronman.taxonomies import LockType
class HelloWorld1(BaseCronJob):
"""Demo Cron Job class (1)"""
lock_type = LockType.CLASS
lock_name = 'HelloWorld'
class HelloWorld2(BaseCronJob):
"""Demo Cron Job class (2)"""
lock_type = LockType.CLASS
lock_name = 'HelloWorld'
配置CPU和IO优先级
我们可以通过使用worker_cpu_priority
属性为cron作业类分配CPU优先级(nice
)。
from cronman.taxonomies import CPUPriority
class NiceHellowWorld(BaseCronJob):
"""Hello World running through `nice -n 19`"""
worker_cpu_priority = CPUPriority.LOWEST
我们还可以通过将cronman.taxonomies.IOPriority
中的某个值分配给worker_io_priority
属性来自定义IO优先级(ionice
),但在大多数情况下,这不是必要的,因为nice
也会改变IO优先级。
命令cron_scheduler run
、cron_worker resume
和cron作业RunCronTasks
将根据分配给cron作业类的CPU和IO优先级启动工作进程。当运行cron_worker run
时,这些设置**不会**强制执行,因此您必须手动将nice
/ionice
添加到此类调用中。
列出和杀死正在运行的cron作业
命令 cron_worker status
显示当前运行的 cron 作业 - PID 文件名、PID 和状态(《ALIVE》或《DEAD》)。可以通过 作业规范
(cron 作业名称、参数)限制搜索结果。
python manage.py cron_worker status
python manage.py cron_worker status Foo
python manage.py cron_worker status Foo:bar=1
命令 cron_worker kill
可以优雅地(通过 SIGTERM
)或强制杀死活跃的 cron 作业(当进程拒绝死亡时使用 SIGKILL
)。可以通过 作业规范
限制任务列表。
python manage.py cron_worker kill
python manage.py cron_worker kill Foo
python manage.py cron_worker kill Foo:bar=1
可以使用 PID 杀死单个进程。
python manage.py cron_worker kill 39078
恢复 cron 作业
在杀死后,可以恢复 cron 作业的子集。
class ResumableHelloWorld(BaseCronJob):
"""Demo Cron Job class"""
can_resume = True
命令 cron_worker resume
以 can_resume
功能启动所有已杀死的 cron 作业。
python manage.py cron_worker resume
要删除有关已死亡 cron 作业的所有条目并确保它们不会恢复,可以运行 cron_worker clean
命令。
python manage.py cron_worker clean
命令 cron_worker suspend
清除有关已死亡 cron 作业的所有先前条目,然后杀死所有正在运行的作业,以确保下一次 resume
只触发最近杀死的作业。
python manage.py cron_worker suspend
列出可用的 cron 作业
命令 cron_worker info
显示所有可用 cron 作业的列表。
python manage.py cron_worker info
当将 cron 作业名称传递给此命令时,系统将显示给定 cron 作业的 docstring 和参数。
python manage.py cron_worker info Foo
禁用调度器
调度器命令可以临时禁用。
python manage.py cron_scheduler disable
并稍后重新启用
python manage.py cron_scheduler enable
当调度器被禁用时,对 cron_scheduler run
的调用将不会启动工作进程。
将错误发送到 Sentry
cron 作业类中的错误被 cron_worker
拦截,并使用与其他 Django 命令相同的配置发送到 Sentry(settings.RAVEN_MANAGEMENT_COMMAND_CONFIG
)。如果定义了 settings.CRONMAN_RAVEN_CMD
,则调度器将使用它作为工作进程的执行脚本,例如 python manage.py cron_worker run Foo:bar=1
将转换为 {CRONMAN_RAVEN_CMD} -c "python manage.py cron_worker run Foo:bar=1"
Cron 任务 - 从管理区域运行 cron 作业
某些 cron 作业可以从管理区域请求启动:管理 > Cron > Cron 任务 要将 cron 作业类添加到管理区域的列表中,我们需要设置 ALLOWED_CRON_TASKS
设置。
ALLOWED_CRON_TASKS = (
'HelloWorld',
)
要请求给定 cron 作业的另一次运行,我们只需在管理区域创建一个新的 CronTask
记录。调度器每 4 分钟启动一次 RunCronTasks
cron 作业将为一个挂起的 Cron 任务启动一个单独的工作进程。
变更日志
2021-01-20 - 3.0.0 删除 Python 2 检查。修复暂停所有的问题。2020-05-25 - 2.1.0 Python 3 + Django 2 兼容性。2020-04-30 - 2.0.1 修复 sentry-sdk 问题。2020-04-23 - 2.0.0 用 sentry-sdk 替换 raven。2020-01-09 - 1.2.0 Django 2 兼容性。2019-04-30 - 1.1.1 Pre-commit.com 钩子支持。文档更新 2019-03-13 - 1.1.0 添加对 cronitor ping 的支持。2019-02-25 - 1.0.0 初始版本发布