跳转到主要内容

用户Crontab安装Buildout配方

项目描述

z3c.recipe.usercrontab

问题

在部署应用程序时,定期启动维护任务可能很有用。在 Unix 平台上,这通常是通过使用 cron 来完成的,它会启动 cronjobs。通过将文件放置在 /etc/cron.d(例如)向系统范围的 cron 目录添加 cronjobs 可以使用 zc.recipe.deployment 包来处理,但它不支持通过普通用户添加 cronjobs。(因为 /etc/cron.d 通常是对所有人可写的)。

解决方案

z3c.recipe.usercrontab 通过使用 crontab(1) 与 cron 进行接口,允许普通用户安装他们自己的 cronjobs。这是通过在安装和卸载软件包时添加和删除 cronjobs 来实现的。

如何使用

要使用 z3c.recipe.usercrontab,您需要将以下内容添加到您的 buildout.cfg 中

[mycronjob]
recipe = z3c.recipe.usercrontab
times = 0 12 * * *
command = echo nothing happens at noon

并最后将 mycronjob 添加到您的 buildout.cfg 的 parts 行中

为您的 cron-entry 添加注释

[mycronjob]
recipe = z3c.recipe.usercrontab
times = 0 12 * * *
command = echo nothing happens at noon
comment = Run daily at noon

如果您更喜欢手动启用 cronjobs,可以通过将 enabled 设置为 False 来生成一个被注释掉的 cron-entry

[mycronjob]
recipe = z3c.recipe.usercrontab
times = 0 12 * * *
command = echo nothing happens at noon
enabled = false

运行 buildout 后,您可以通过 crontab -l 检查生成的 cron-entries。

致谢

原始作者:Jasper Spaans 和 Jan-Jaap Driessen。

最新版本和当前维护者:Reinout van Rees

详细文档

z3c.recipe.usercrontab 脚本是用于方便将 cronjobs 安装到用户 crontabs 的小型脚本来。

>>> from z3c.recipe.usercrontab.usercrontab import UserCrontabManager

条目处理

一个用户 crontab 管理器管理一个特定 buildout 部分的用户的 crontab。该部分最终在标识符中结束。我们将在这里使用“test”。

>>> c = UserCrontabManager(identifier='test')

在这些测试中,我们可以通过手动填写 cron 条目的列表来模拟 crontab

>>> c.crontab = ['@reboot echo "hello world"']
>>> print(c) # Handy shortcut
@reboot echo "hello world"

现在,我们使用官方方式向其中添加一个条目。该条目被标记包围

>>> c.add_entry('@reboot echo "I just got added"')
>>> print(c)
@reboot echo "hello world"
<BLANKLINE>
# Generated by test
@reboot echo "I just got added"
# END test
<BLANKLINE>

删除条目也有效。只要存在“由生成的”标记,就不重要您删除哪个条目:所有被标记包围的内容都会被清除

>>> c.del_entry('bla bla') == 1
True
>>> print(c)
@reboot echo "hello world"

一个条目也可以包含一个解释性的注释行

>>> c.add_entry('@reboot echo "I just got added"',
...     comment="This ought to happen first")
>>> print(c)
@reboot echo "hello world"
<BLANKLINE>
# Generated by test
# This ought to happen first
@reboot echo "I just got added"
# END test
<BLANKLINE>

在 0.6 版本之前,使用了一个 WARNING 环境变量。一个条目(现在的内容很重要!)在那里找到

>>> c.crontab = ['@reboot echo "hello world"',
...              'WARNING="Everything below is added by bla bla',
...              '@reboot echo "old entry 1"',
...              '@reboot echo "old entry 2"']
>>> print(c)
@reboot echo "hello world"
WARNING="Everything below is added by bla bla
@reboot echo "old entry 1"
@reboot echo "old entry 2"
>>> c.del_entry('@reboot echo "old entry 1"')
1
>>> print(c)
@reboot echo "hello world"
WARNING="Everything below is added by bla bla
@reboot echo "old entry 2"

删除最后一个剩余的 WARNING 条目也会删除 WARNING

>>> c.del_entry('@reboot echo "old entry 2"')
1
>>> print(c)
@reboot echo "hello world"

简要地,在 0.5 版本中,使用了一个 ‘BUILDOUT’ 环境变量来按 buildout 对项目进行分组。现在进行一些升级/降级测试。0.5.1 再次删除了环境变量。我们将添加一个带有这样的(现在已弃用的)“分组环境变量”的条目。首先是起始情况

>>> c.crontab=[
...     'WARNING="Everything below is added by bla bla',
...     'BUILDOUT=my/buildout',
...     '@reboot echo nothing happens']
>>> print(c)
WARNING="Everything below is added by bla bla
BUILDOUT=my/buildout
@reboot echo nothing happens

进行任何操作(添加/删除)都会清除 BUILDOUT 语句

>>> c.del_entry('nonexisting')
0
>>> print(c)
WARNING="Everything below is added by bla bla
@reboot echo nothing happens

并且为了确保这一点,删除该条目会清空整个文件

>>> c.del_entry('@reboot echo nothing happens')
1
>>> print(c)
<BLANKLINE>

读写 crontab 方法

接下来,测试 read_crontab 和 write_crontab 方法;我们将使用 cat 和一个临时文件,以不修改运行这些测试的用户的 crontab

>>> import tempfile
>>> t = tempfile.NamedTemporaryFile('w')
>>> crontestfile = t.name
>>> dont_care = t.write("#dummy\n")
>>> c = UserCrontabManager(readcrontab="cat %s" % crontestfile,
...                        writecrontab="cat >%s" % crontestfile,
...                        identifier='test')
>>> c.read_crontab()
>>> a = repr(c)
>>> c.add_entry('# improbable entry')
>>> c.write_crontab()
>>> c.read_crontab()
>>> b =repr(c)
>>> a == b
False

现在,再次删除此条目,并确保恢复旧 crontab

>>> c.del_entry('# improbable entry') == 1
True
>>> c.write_crontab()
>>> c.read_crontab()
>>> b = repr(c)
>>> a == b
True

Buildout 脚本使用

进行 buildout 交换

>>> write('buildout.cfg',
... '''
... [buildout]
... parts = foo
...
... [foo]
... recipe = z3c.recipe.usercrontab
... times = @reboot
... command = echo nothing happens
... readcrontab = cat %(crontest)s
... writecrontab = cat >%(crontest)s
... ''' % ( { 'crontest': crontestfile } ))
>>> import os
>>> 'Installing foo' in system(buildout)
True

检查它是否确实已添加到 crontab 中

>>> c.read_crontab()
>>> b = repr(c)
>>> a == b
False
>>> '@reboot\techo nothing happens' in c.crontab
True
>>> print(c)
# Generated by /sample-buildout [foo]
@reboot   echo nothing happens
# END /sample-buildout [foo]

重新运行 buildout 即使没有变化也会运行 crontab 脚本

>>> output = system(buildout)
>>> 'Updating foo' in output or 'Installing foo' in output
True
>>> c.read_crontab()
>>> print(c)
# Generated by /sample-buildout [foo]
@reboot echo nothing happens
# END /sample-buildout [foo]

这意味着如果手动弄乱了 crontab,则可以修复 crontab

>>> c.crontab = []
>>> c.write_crontab()
>>> c.read_crontab()
>>> print(c)
>>> output = system(buildout)
>>> 'Updating foo' in output or 'Installing foo' in output
True
>>> c.read_crontab()
>>> print(c)
# Generated by /sample-buildout [foo]
@reboot echo nothing happens
# END /sample-buildout [foo]

您还可以向 crontab 条目添加注释

>>> write('buildout.cfg',
... '''
... [buildout]
... parts = foo
...
... [foo]
... recipe = z3c.recipe.usercrontab
... times = @reboot
... command = echo nothing happens
... comment = Step 1: mention that nothing happens
... readcrontab = cat %(crontest)s
... writecrontab = cat >%(crontest)s
... ''' % ( { 'crontest': crontestfile } ))
>>> 'Installing foo' in system(buildout)
True
>>> c.read_crontab()
>>> print(c)
# Generated by /sample-buildout [foo]
# Step 1: mention that nothing happens
@reboot echo nothing happens
# END /sample-buildout [foo]

默认情况下,条目是启用的,导致 cronjob 激活

>>> write('buildout.cfg',
... '''
... [buildout]
... parts = foo
...
... [foo]
... recipe = z3c.recipe.usercrontab
... times = @reboot
... command = echo nothing happens
... enabled = true
... readcrontab = cat %(crontest)s
... writecrontab = cat >%(crontest)s
... ''' % ( { 'crontest': crontestfile } ))
>>> 'Installing foo' in system(buildout)
True
>>> c.read_crontab()
>>> print(c)
# Generated by /sample-buildout [foo]
@reboot echo nothing happens
# END /sample-buildout [foo]

您还可以生成一个已禁用的、被注释掉的cronjob,通过设置启用选项为False。

>>> write('buildout.cfg',
... '''
... [buildout]
... parts = foo
...
... [foo]
... recipe = z3c.recipe.usercrontab
... times = @reboot
... command = echo nothing happens
... enabled = false
... readcrontab = cat %(crontest)s
... writecrontab = cat >%(crontest)s
... ''' % ( { 'crontest': crontestfile } ))
>>> 'Installing foo' in system(buildout)
True
>>> c.read_crontab()
>>> print(c)
# Generated by /sample-buildout [foo]
# @reboot echo nothing happens
# END /sample-buildout [foo]

卸载食谱

>>> write('buildout.cfg',
... '''
... [buildout]
... parts =
... ''' % ( { 'crontest': crontestfile } ))
>>> 'Uninstalling foo' in system(buildout)
True

并检查其条目已被删除(即,crontab的内容与测试开始时相同;无论如何,testrunner的拆卸确保旧状态被恢复)

>>> c.read_crontab()
>>> b = repr(c)
>>> a == b
True

第二部分安装正常

>>> write('buildout.cfg',
... '''
... [buildout]
... parts = foo bar
...
... [foo]
... recipe = z3c.recipe.usercrontab
... times = @reboot
... command = echo nothing happens
... readcrontab = cat %(crontest)s
... writecrontab = cat >%(crontest)s
...
... [bar]
... recipe = z3c.recipe.usercrontab
... times = @reboot
... command = echo something happens
... readcrontab = cat %(crontest)s
... writecrontab = cat >%(crontest)s
... ''' % ( { 'crontest': crontestfile } ))
>>> output = system(buildout)
>>> 'Installing foo' in output
True
>>> 'Installing bar' in output
True
>>> c.read_crontab()
>>> print(c)
<BLANKLINE>
# Generated by /sample-buildout [foo]
@reboot   echo nothing happens
# END /sample-buildout [foo]
<BLANKLINE>
<BLANKLINE>
# Generated by /sample-buildout [bar]
@reboot   echo something happens
# END /sample-buildout [bar]
<BLANKLINE>

卸载也正常工作

>>> write('buildout.cfg',
... '''
... [buildout]
... parts =
... ''' % ( { 'crontest': crontestfile } ))
>>> output = system(buildout)
>>> 'Uninstalling bar' in output
True
>>> 'Uninstalling foo' in output
True

安全阀

如果该部分已被删除,卸载将找不到任何内容。您将收到警告。

>>> write('buildout.cfg',
... '''
... [buildout]
... parts = foo
...
... [foo]
... recipe = z3c.recipe.usercrontab
... times = @reboot
... command = echo nothing happens
... readcrontab = cat %(crontest)s
... writecrontab = cat >%(crontest)s
... ''' % ( { 'crontest': crontestfile } ))
>>> import os
>>> 'Installing foo' in system(buildout)
True
>>> c.crontab = []
>>> c.write_crontab()
>>> write('buildout.cfg',
... '''
... [buildout]
... parts =
... ''' % ( { 'crontest': crontestfile } ))
>>> 'WARNING: Did not find a crontab-entry during uninstall' in system(buildout)
True

另一个测试:0.6之前的配置模拟

>>> write('buildout.cfg',
... '''
... [buildout]
... parts = foo
...
... [foo]
... recipe = z3c.recipe.usercrontab
... times = @reboot
... command = echo nothing happens
... readcrontab = cat %(crontest)s
... writecrontab = cat >%(crontest)s
... ''' % ( { 'crontest': crontestfile } ))
>>> import os
>>> 'Installing foo' in system(buildout)
True
>>> c.crontab = ['WARNING="Everything below is added by bla bla"',
...              'BUILDOUT=/somewhere/out/there',
...              '@reboot\techo nothing happens']
>>> c.write_crontab()
>>> write('buildout.cfg',
... '''
... [buildout]
... parts =
... ''' % ( { 'crontest': crontestfile } ))
>>> 'Running uninstall recipe' in system(buildout)
True
>>> c.read_crontab()
>>> print(c)
<BLANKLINE>

z3c.recipe.usercrontab更改

1.5 (2018-12-20)

  • 官方支持Python 3.5、3.6、3.7、PyPy和PyPy3。

1.4 (2015-10-29)

  • 增加了一个默认开启的启用选项。通过将其设置为false,您可以生成被注释掉的cronjob。

    如果您必须在cronjob被开启(通过手动取消注释或脚本)之前在部署中执行其他任务,这将很有用。[WouterVH]

1.3 (2015-10-05)

  • 新增了一个‘comment’选项。这样您可以为您的crontab条目添加一行简短的说明。[reinout]

1.2.1 (2015-09-11)

1.1 (2010-11-09)

  • 每个cron条目减少前后空白空格,这样在每次运行bin/buildout时都不会有越来越多的额外空格。[maurits]

1.0 (2009-11-10)

  • 仅对文档进行了小的修改;版本提升到1.0以表示稳定性。[reinout]

0.7 (2009-08-24)

  • 现在每次buildout运行时都会检查crontab,而不仅仅是配置发生变化时。[reinout]

0.6.1 (2009-06-17)

  • 文档修复。[reinout]

0.6 (2009-06-16)

  • 删除了基本上未使用的完整环境变量处理。[reinout]

  • 现在添加带有描述性注释的条目:包括buildout文件和部分名称。[reinout]

0.5.1 (2009-06-16)

  • 撤销了“BUILDOUT=…”环境变量,包括迁移。我将在这次发布后添加更好的方法。[reinout]

0.5 (2009-06-15)

  • 为没有BUILDOUT变量的0.5之前的条目添加了迁移代码。[reinout]

  • 在“BUILDOUT=…”变量前面添加了额外的空白行,以便于更好的可读性。[reinout]

  • 将每个由一个buildout处理的crontab行的“BUILDOUT=…”作为环境变量添加。这使得更容易找出哪个buildout添加了什么(如果您有多个),或者哪个buildout(如果您不知道buildout在哪里)。

0.4 (2008-02-25)

  • 修复了UserCrontabs带有空readcrontab和writecrontab构造函数参数时的错误

0.3 (2008-02-23)

  • 重命名为z3c.recipe.usercrontab

  • 添加了一个选项来更改用于读取和写入crontabs的命令

  • 改进了测试,以不修改真实的crontab

0.2 (2008-01-12)

  • 如果buildout卸载中无法删除条目,则发出警告

  • 如果buildout卸载中要删除多个条目,则中断

  • 让del_entry返回删除的数量

0.1 (2008-01-12)

  • 初始发布。

项目详情


下载文件

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

源代码分发

z3c.recipe.usercrontab-1.5.tar.gz (17.3 kB 查看哈希)

上传于 源码

支持