你如何将定时任务部署到生产环境?

24

人们如何将cronjobs部署/版本控制到生产环境中?我更关心人们使用的惯例/标准,而不是任何特定的解决方案,但我碰巧正在使用git进行修订控制,并且cronjob正在运行一个python/django脚本。

9个回答

23
如果你正在使用Fabric进行部署,你可以添加一个函数来编辑你的crontab。
def add_cronjob():
    run('crontab -l > /tmp/crondump')             
    run('echo "@daily /path/to/dostuff.sh 2> /dev/null" >> /tmp/crondump')
    run('crontab /tmp/crondump')

这将向您的crontab追加作业(免责声明:完全未经测试,不是非常幂等)。
  1. 将crontab保存到临时文件中。

  2. 向tmpfile追加一行。

  3. 将crontab写回。

这可能不是您想要做的确切操作,但您可以考虑将crontab检入git,并在每次部署时使用专用用户覆盖它。(如果有为您的项目分配的用户。)

实际上,如果您修改cron行,则使用Fabric的append命令不是幂等的。您最终会得到旧行和新行。 - Dave
2
我必须在创建/tmp/crondump时添加语法来列出crontab,否则它将会卡住(至少在Ubuntu上是这样)。 (即“crontab -l> / tmp / crondump”) - joet3ch
我正在使用这种方法在我的生产服务器上安装crontab,但它不起作用。它什么也不做,即使当我通过SSH登录到服务器并检查crontab -l时,一切似乎都很正常。我注意到,如果我使用crontab -e进行编辑,即使我只添加一个无意义的空格,当我保存文件时,它会显示“安装新的crontab”,然后开始工作。有任何想法为什么会发生这种情况吗? - Juan Enrique Muñoz Zolotoochin
我认为它是幂等的:“如果文本已经在文件名中找到,则不会运行附加操作,并立即返回None。否则,给定的文本将通过例如echo '$text' >> $filename附加到给定文件名的末尾。” - bluszcz
1
与其追加,最好是将整个crontab文件存储在您的repo中,并在部署时替换整个文件。这意味着您可以轻松删除和编辑行,并确切地知道服务器上任何时间都有什么。而且实际上变得更简单。请参见Jesse的答案。 - Jonathan Hartley

10

使用Fabric,我更喜欢在本地保持一个原始版本的crontab,这样我就知道生产环境上的确切内容,并且可以轻松地编辑条目以及添加它们。

我使用的Fabric脚本看起来像这样(某些代码已被删除,例如备份处理):

def deploy_crontab():
    put('crontab', '/tmp/crontab')
    sudo('crontab < /tmp/crontab')

4

1
我喜欢将项目及其crontab.txt文件纳入版本控制。然后,使用Fabric非常简单:
@task
def crontab():
    run('crontab deployment/crontab.txt')

这将安装deployment/crontab.txt文件的内容到您连接到服务器的用户的定时任务列表中。如果您在服务器上没有完整的项目,您需要首先put定时任务文件。

1

如果您无法将系统连接到配置管理系统(如cfengine/puppet),则手动部署crontab实际上有3个选项。

您可以简单地使用crontab -u user -e,但是您可能会冒着某人复制/粘贴时出现错误的风险。

您还可以将文件复制到cron目录中,但是该文件没有语法检查,在Linux中,您必须运行touch /var/spool/cron才能使crond捕获更改。

注意:每个人都会在某个时候忘记touch命令。

根据我的经验,这种方法是我最喜欢的手动部署crontab的方式。

diff /var/spool/cron/<user> /var/tmp/<user>.new
crontab -u <user> /var/tmp/<user>.new

我认为我上面提到的方法是最好的,因为您不会遇到复制/粘贴错误的风险,这有助于您与版本控制文件保持一致性。它执行文件内 cron 任务的语法检查,如果您只是复制文件,则无需执行 touch 命令。

“部署”一词意味着完全自动化的过程。不应该有任何手动操作,也不需要检查差异以了解正在发生的变化。一个命令完成整个过程,没有其他额外步骤。(例如:“fab staging deploy:v1.23”) - Jonathan Hartley

1

你可以使用像CFEngine/Chef这样的工具进行部署(它可以部署所有东西,包括cron作业)。

然而,如果你问这个问题,可能是因为你有许多生产服务器,每个服务器都运行大量的计划任务。 如果是这种情况,你可能需要一个工具,不仅可以部署作业,还可以跟踪成功或失败,允许你轻松查看上次运行的日志、运行统计数据,允许你轻松更改许多作业和服务器的计划表(由于计划维护等原因)等等。

我使用了一个商业工具叫做“UC4”。我并不是真正推荐它,所以我希望你能找到一个更好的程序来解决同样的问题。我只是想说,作业管理并不仅仅在部署它们时结束。


0

0
如果您正在使用Django,请查看{{link1:django-command-extensions中的作业系统}}。
好处是您可以将作业保留在项目结构内,进行版本控制,全部用Python编写,并仅配置crontab一次。

0

你说:

我更好奇人们使用的惯例/标准,而不是任何特定的解决方案

但是,公平地说,特定的解决方案将取决于您的环境,并且没有通用的优雅银弹。鉴于您正在使用Python/Django,我建议使用Celery。它是Python的异步任务队列,与Django很好地集成。除了作为异步任务队列提供的功能之外,它还具有特定的定期任务功能。

我个人使用了django-celery-beat集成,它与Django设置完美集成,并在分布式环境中正确运行。如果您的定期任务与Django相关,请强烈建议查看Celery。我最初只用于某些异步邮件,最终用于许多异步任务+定期的健全性检查和其他Web应用程序维护工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接