跳转到主要内容

通过Django的admin轻松控制cron作业。

项目描述

Chroniker - Django受控cron作业

Build Status

概述

Django Chroniker是一个Python包,允许您通过Django的admin使用cron调度Django管理命令。

为Django应用程序创建cron作业可能很痛苦、令人烦恼且重复。使用django-chroniker,您只需创建一个每分钟运行一次的cron作业,将其指向您的站点目录并运行manage.py cron。然后,您可以通过Django的admin创建、更新和删除作业。

这是Weston Nielson的Chronograph项目的分支。

功能

与父Chronograph项目相比,此包包含以下改进

  • 允许Django管理命令记录它们的百分比进度并在admin中显示它。例如。

      from chroniker.models import Job
      Job.update_progress(total_parts=77, total_parts_complete=13)
    
  • 改进了管理命令的stdout和stderr的记录,并有效地在admin中显示这些信息。

  • 创建了一个名为Monitor的模型,它是Job模型的代理,以便更容易地设置系统和数据库状态监控。

  • 添加了一个模型来记录作业之间的依赖关系,以及基于这些依赖关系控制作业行为的标志。例如,您可以配置一个作业,直到另一个作业成功运行后才运行,或者在未来某个日期运行。

  • 改进了在多服务器环境中协调作业执行的支持。例如,您可以配置一个作业仅在特定主机上或任何主机上运行。

与一些调度系统不同,Chroniker试图确保在任何给定时间最多只有一个作业运行实例。这大大简化了调度,但必然会施加一些限制。如果您需要同时调度多个任务实例,尤其是在实时情况下,请考虑使用类似Celery的系统。

安装

使用pip从PyPI安装包:

pip install django-chroniker

或者直接从GitHub安装(警告:这可能比PyPI上的官方版本不稳定):

pip install https://github.com/chrisspen/django-chroniker/tarball/master

将'chroniker'和'django.contrib.sites'添加到您的settings.py中的INSTALLED_APPS列表中,如下所示:

INSTALLED_APPS = (
...
'django.contrib.sites',
'chroniker',
...
)

如果您使用的是Django 1.7或更高版本(您应该这样做),通过运行以下命令安装Chroniker的模型:

python manage.py migrate

否则运行:

python manage.py syncdb

用法

在您的管理界面中,在Chroniker部分创建和配置任务。

如果您处于开发环境,可以通过首先在您的任务上检查“强制运行”,然后运行以下命令来测试基于Chroniker的cron作业:

python manage.py cron

此外,您可以使用以下命令模拟一个简单的cron服务器,该服务器将每N秒自动运行任何挂起的cron作业:

python manage.py cronserver

为了允许Chroniker发送电子邮件,请确保您在settings.py中设置了有效的电子邮件参数。以下是一个使用Gmail的非常基本的示例:

EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = 'myusername@gmail.com'
EMAIL_HOST_PASSWORD = os.environ['GMAILPASS']

您可以使用以下方式自定义Chroniker在其电子邮件中使用的“名称”:

CHRONIKER_EMAIL_SENDER = 'Jon Doe'

您还可以使用以下方式为Chroniker指定单独的电子邮件用户:

CHRONIKER_EMAIL_HOST_USER = 'someotherusername@otherdomain.com'

在生产环境中安装Chroniker时,您需要添加一个调用bin/chronikerpython manage.py cron的单个cron作业。在调用中,您需要指定此脚本安装的位置,您的Python虚拟环境的位置(如果您正在使用),以及您的Django项目的位置。以下是一个示例:

* * * * * /usr/local/myproject/bin/chroniker -e /usr/local/myproject/.env/bin/activate_this.py -p /usr/local/myproject

运行bin/chroniker --help以获取完整选项列表。

设置

根据您的使用情况,有一些选项可能会极大地帮助或妨碍作业调度。

CHRONIKER_USE_PID

  • 如果设置为True,则cron管理命令将等待上一次运行完成,使用本地PID文件。

CHRONIKER_SELECT_FOR_UPDATE

  • 如果设置为True,则更新数据库中的作业状态时,作业记录将锁定(可能不支持所有数据库后端)。

CHRONIKER_CHECK_LOCK_FILE

  • 如果设置为True,Chroniker将检查本地锁文件以确定作业是否正在运行。
  • 您应该在单服务器环境中将其设置为True,在多服务器环境中设置为False。

CHRONIKER_DISABLE_RAW_COMMAND

  • 如果设置为True,Chroniker将不会运行原始命令。这减少了在不信任的访问者可以访问管理界面时攻击面。

维护

如果您想要一种简单的方法来删除旧作业日志,有一个管理命令可以为您完成:cron_clean。您可以像这样使用它:

python manage.py cron_clean [weeks|days|hours|minutes] [integer]

因此,如果您想删除所有一周以上的作业,可以这样做:

python manage.py cron_clean weeks 1

由于这只是简单的管理命令,您也可以很容易地将其添加到chroniker中,通过管理界面,这样它将自动清除旧日志。

工具

还有一个包含的管理命令cronserver,可以用来测试作业的定期运行。它会将有关哪些作业即将到期以及运行它们的信息打印到屏幕上。以下是您可以使用它的方法:

python manage.py cronserver

这将启动一个进程,该进程将每60秒检查并运行任何即将到期的作业。间隔可以通过简单地传递两次运行之间的秒数来更改。例如,要使进程每2分钟检查一次即将到期的作业,您将运行:

python manage.py cronserver 120

架构

Chroniker 中,最难正确处理的事情是管理 Job 的状态,即可靠地确定一个作业是否正在运行,或者它是否已经被终止或提前终止。在 Chroniker 的第一个版本中,这个问题通过跟踪每个正在运行的作业的 PID 并使用 ps 命令让操作系统告诉我们作业是否仍在运行来“解决”。然而,这种方法并不理想,原因有几个,但最重要的是它不是跨平台的。此外,使用一系列 subprocess.Popen 调用导致一些用户在“支持的平台”上出现路径相关的问题。

较新版本的 Chroniker 尝试以下方法解决这个问题

1.  Get a list of ``Job``\s that are "due"
2.  For each ``Job``, launch a ``multiprocessing.Process`` instance, which
    internally calls ``django.core.management.call_command``
3.  When the ``Job`` is run, we spawn a ``threading.Thread`` instance whose
    sole purpose is to keep track of a lock file.  This thread exists only
    while the Job is running and updates the file every second.  We store
    the path to this temporary file (an instance of
    ``tempfile.NamedTemporaryFile``) on the ``Job`` model (which is then
    stored in the database).  When we want to check if a ``Job`` is running
    we do the following:
    
    1.  If ``is_running`` equals ``True``, and ``lock_file`` point to a
        file, then:
        
        1.  If the lock file actually exists and has been updated more
            recently than ``CHRONIKER_LOCK_TIMEOUT`` seconds, then we
            can assume that the ``Job`` is still running
    2.  Else we assume the ``Job`` is not running and update the database
        accordingly

这种新方法应该会在所有支持线程和多进程库的平台上有更高的可靠性。

开发

要跨多个 Python 版本运行单元测试,请安装

sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt-get update
sudo apt-get install python-dev python3-dev python3.3-minimal python3.3-dev python3.4-minimal python3.4-dev python3.5-minimal python3.5-dev python3.6 python3.6-dev

要运行所有 测试

export TESTNAME=; tox

要为特定环境(例如 Python 3.8 与 Django 3.0)运行测试

export TESTNAME=; tox -e py38-django30

要运行特定的测试

export TESTNAME=.testTimezone2; tox -e py38-django30

要本地运行 文档服务器

mkdocs serve -a :9999

部署文档,请运行

mkdocs gh-deploy --clean

要构建并部署带有版本号的包到 PyPI,请验证 所有单元测试都通过,然后运行

python setup.py sdist
python setup.py sdist upload

要提交时跳过 pre-commit 检查钩子

SKIP=yapf git commit -m "foo"

项目详情


下载文件

下载您平台上的文件。如果您不确定选择哪个,请了解更多关于 安装包 的信息。

源分发

django-chroniker-1.0.24.tar.gz (100.3 kB 查看哈希)

上传时间

由以下支持

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面