跳转到主要内容

Redhat RC脚本的ZC Buildout配方

项目描述

此软件包提供了一种zc.buildout配方,用于创建与Red-Hat Linux兼容的运行控制脚本。

变更

1.4.2 (2012-12-20)

修复:如果在卸载过程中停止运行脚本失败时引发错误。

这可能导致buildout卡住,因为您无法卸载损坏的/丢失的运行脚本。

1.4.1 (2012-08-31)

修复:更新时未启动进程。

在理想的世界里,这不会是必要的,因为在更新情况下,进程已经正在运行,但是,尝试启动进程以确保进程正在运行是有帮助的。

1.4.0 (2012-05-18)

  • 添加了可选的进程管理支持。如果请求,则运行脚本作为安装和卸载的一部分运行。

  • 修复:缺少对zope.testing测试依赖关系。

1.3.0 (2010/05/26)

新功能

  • 一个新的独立进程选项导致多个进程独立重新启动,而不是停止所有进程然后重新启动所有进程。

已修复的漏洞

  • 生成的运行脚本有尾随空格。

1.2.0 (2009/04/06)

显示在启动、停止或重新启动时每个脚本正在运行的脚本名称

1.1.0 (2008/02/01)

在生成脚本名称时,如果存在,请使用部署名称选项(由zc.recipe.deployment 0.6.0及以后版本提供)。

当使用部署时,请使用部署rc目录作为目标。

请使用/sbin/chkconfig而不是chkconfig,因为据说它始终在该位置,很少在任何人路径中。 :)

1.0.0 (2008/01/15)

首次公开发布

详细文档

创建Red-Hat Linux(chkconfig)rc脚本

zc.recipes.rhrc 食谱创建 Red Hat Linux (chkconfig) rc 脚本。它可以创建单个 rc 脚本,以及启动多个应用程序的组合 rc 脚本。

该食谱有一个 parts 选项,它接受定义运行脚本的节名称。它们应该是

  • 定义一个包含单行 shell 脚本的运行脚本选项,或者

  • 存在文件 /etc/init.d/PART,其中 PART 是部分名称。

一个简单的例子可能会使这一点更加清晰。

>>> demo = tmpdir('demo')
>>> write('buildout.cfg',
... """
... [buildout]
... parts = zoperc
...
... [zoperc]
... recipe = zc.recipe.rhrc
... parts = zope
... dest = %(dest)s
...
... [zope]
... run-script = /opt/zope/bin/zopectl -C /etc/zope.conf
... """ % dict(dest=demo))

通常,该食谱会将脚本写入 /etc/init.d。我们可以覆盖目标,就像我们在这里所做的那样,使用演示目录。我们指定了它应该从 zope 节获取运行脚本源。在这里,zope 节只是一个配置节,其中运行脚本选项被直接设置,但它也可以是一个具有从食谱计算出的运行脚本选项的部分。

如果我们运行 buildout

>>> print system('bin/buildout'),
Installing zoperc.

我们将在我们的演示目录中获得 zoperc 脚本

>>> ls(demo)
-  zoperc
>>> cat(demo, 'zoperc')
#!/bin/sh
<BLANKLINE>
# This script is for adminstrator convenience.  It should
# NOT be installed as a system startup script!
<BLANKLINE>
<BLANKLINE>
case $1 in
  stop)
<BLANKLINE>
    /opt/zope/bin/zopectl -C /etc/zope.conf $*
<BLANKLINE>
    ;;
  restart)
<BLANKLINE>
    ${0} stop
    sleep 1
    ${0} start
<BLANKLINE>
    ;;
  *)
<BLANKLINE>
    /opt/zope/bin/zopectl -C /etc/zope.conf $*
<BLANKLINE>
    ;;
esac
<BLANKLINE>

关于生成的脚本有几个需要注意的地方

  • 它使用 $* 传递参数,因此参数不能被引号括起来。这是可以的,因为参数将是简单的动词,如启动和停止。

  • 它包括一条注释,说明该脚本不应作为系统启动脚本使用。

为了使脚本用于系统启动,我们需要指定运行级别信息。我们可以使用 chkconfig 选项来做到这一点

>>> write('buildout.cfg',
... """
... [buildout]
... parts = zoperc
...
... [zoperc]
... recipe = zc.recipe.rhrc
... parts = zope
... dest = %(dest)s
... chkconfig = 345 90 10
... chkconfigcommand = echo
...
... [zope]
... run-script = /opt/zope/bin/zopectl -C /etc/zope.conf
... """ % dict(dest=demo))

在这里,我们包括了一个 chkconfig 选项,表示 Zope 应该在运行级别 3、4 和 5 上启动,并且它的启动和停止顺序应该是 90 和 10。

出于演示目的,我们并不真的想运行 chkconfig,所以我们使用 chkconfigcommand 选项告诉食谱运行 echo。

>>> print system('bin/buildout'),
Uninstalling zoperc.
Running uninstall recipe.
Installing zoperc.
--add zoperc

现在脚本包含一个 chkconfig 注释

>>> cat(demo, 'zoperc')
#!/bin/sh
<BLANKLINE>
# the next line is for chkconfig
# chkconfig: 345 90 10
# description: please, please work
<BLANKLINE>
<BLANKLINE>
case $1 in
  stop)
<BLANKLINE>
    /opt/zope/bin/zopectl -C /etc/zope.conf $* \
      </dev/null
<BLANKLINE>
    ;;
  restart)
<BLANKLINE>
    ${0} stop
    sleep 1
    ${0} start
<BLANKLINE>
    ;;
  *)
<BLANKLINE>
    /opt/zope/bin/zopectl -C /etc/zope.conf $* \
      </dev/null
<BLANKLINE>
    ;;
esac
<BLANKLINE>

我们可以指定脚本应该以哪个用户运行

>>> write('buildout.cfg',
... """
... [buildout]
... parts = zoperc
...
... [zoperc]
... recipe = zc.recipe.rhrc
... parts = zope
... dest = %(dest)s
... chkconfig = 345 90 10
... chkconfigcommand = echo
... user = zope
...
... [zope]
... run-script = /opt/zope/bin/zopectl -C /etc/zope.conf
... """ % dict(dest=demo))
>>> print system('bin/buildout'),
Uninstalling zoperc.
Running uninstall recipe.
--del zoperc
Installing zoperc.
--add zoperc

注意 –del 输出。如果我们没有将 chkconfigcommand 设置为 echo,那么 chkconfig –del 就会在 zoperc 脚本上运行。

>>> cat(demo, 'zoperc')
#!/bin/sh
<BLANKLINE>
# the next line is for chkconfig
# chkconfig: 345 90 10
# description: please, please work
<BLANKLINE>
<BLANKLINE>
if [ $(whoami) != "root" ]; then
  echo "You must be root."
  exit 1
fi
<BLANKLINE>
case $1 in
  stop)
<BLANKLINE>
    su zope -c \
      "/opt/zope/bin/zopectl -C /etc/zope.conf $*" \
      </dev/null
<BLANKLINE>
    ;;
  restart)
<BLANKLINE>
    ${0} stop
    sleep 1
    ${0} start
<BLANKLINE>
    ;;
  *)
<BLANKLINE>
    su zope -c \
      "/opt/zope/bin/zopectl -C /etc/zope.conf $*" \
      </dev/null
<BLANKLINE>
    ;;
esac
<BLANKLINE>

注意现在使用 su 命令来运行脚本。因为脚本被包含在双引号中,所以它不能包含双引号。(食谱不尝试转义双引号。)

还请注意,现在脚本必须以 root 用户运行,所以生成的脚本会检查 root 是否在运行它。

如果我们说用户是 root

>>> write('buildout.cfg',
... """
... [buildout]
... parts = zoperc
...
... [zoperc]
... recipe = zc.recipe.rhrc
... parts = zope
... dest = %(dest)s
... chkconfig = 345 90 10
... chkconfigcommand = echo
... user = root
...
... [zope]
... run-script = /opt/zope/bin/zopectl -C /etc/zope.conf
... """ % dict(dest=demo))

那么生成的脚本将不会使用 su,但它仍然会检查 root 是否在运行它

>>> print system('bin/buildout'),
Uninstalling zoperc.
Running uninstall recipe.
--del zoperc
Installing zoperc.
--add zoperc
>>> cat(demo, 'zoperc')
#!/bin/sh
<BLANKLINE>
# the next line is for chkconfig
# chkconfig: 345 90 10
# description: please, please work
<BLANKLINE>
<BLANKLINE>
if [ $(whoami) != "root" ]; then
  echo "You must be root."
  exit 1
fi
<BLANKLINE>
case $1 in
  stop)
<BLANKLINE>
    /opt/zope/bin/zopectl -C /etc/zope.conf $* \
      </dev/null
<BLANKLINE>
    ;;
  restart)
<BLANKLINE>
    ${0} stop
    sleep 1
    ${0} start
<BLANKLINE>
    ;;
  *)
<BLANKLINE>
    /opt/zope/bin/zopectl -C /etc/zope.conf $* \
      </dev/null
<BLANKLINE>
    ;;
esac
<BLANKLINE>

定义运行脚本的部件还可以通过提供 env 选项来定义用于 rc 脚本的环境变量设置

>>> write('buildout.cfg',
... """
... [buildout]
... parts = zoperc
...
... [zoperc]
... recipe = zc.recipe.rhrc
... parts = zope
... dest = %(dest)s
... chkconfig = 345 90 10
... chkconfigcommand = echo
... user = zope
...
... [zope]
... run-script = /opt/zope/bin/zopectl -C /etc/zope.conf
... env = LD_LIBRARY_PATH=/opt/foolib
... """ % dict(dest=demo))
>>> print system('bin/buildout'),
Uninstalling zoperc.
Running uninstall recipe.
--del zoperc
Installing zoperc.
--add zoperc
>>> cat(demo, 'zoperc')
#!/bin/sh
<BLANKLINE>
# the next line is for chkconfig
# chkconfig: 345 90 10
# description: please, please work
<BLANKLINE>
<BLANKLINE>
if [ $(whoami) != "root" ]; then
  echo "You must be root."
  exit 1
fi
<BLANKLINE>
case $1 in
  stop)
<BLANKLINE>
    LD_LIBRARY_PATH=/opt/foolib \
      su zope -c \
      "/opt/zope/bin/zopectl -C /etc/zope.conf $*" \
      </dev/null
<BLANKLINE>
    ;;
  restart)
<BLANKLINE>
    ${0} stop
    sleep 1
    ${0} start
<BLANKLINE>
    ;;
  *)
<BLANKLINE>
    LD_LIBRARY_PATH=/opt/foolib \
      su zope -c \
      "/opt/zope/bin/zopectl -C /etc/zope.conf $*" \
      </dev/null
<BLANKLINE>
    ;;
esac
<BLANKLINE>

与现有控制脚本一起工作

在上面的例子中,我们基于命令行生成了一个脚本。如果我们有一个创建控制脚本的部件,那么它可以省略运行脚本选项,并且它已经创建的运行脚本将被使用。让我们自己创建一个运行脚本

>>> write(demo, 'zope', '/opt/zope/bin/zopectl -C /etc/zope.conf $*')

现在我们可以从 Zope 节中删除运行脚本选项

>>> write('buildout.cfg',
... """
... [buildout]
... parts = zoperc
...
... [zoperc]
... recipe = zc.recipe.rhrc
... parts = zope
... dest = %(dest)s
... chkconfig = 345 90 10
... chkconfigcommand = echo
... user = zope
...
... [zope]
... env = LD_LIBRARY_PATH=/opt/foolib
... """ % dict(dest=demo))
>>> print system('bin/buildout'),
Uninstalling zoperc.
Running uninstall recipe.
--del zoperc
Installing zoperc.
--add zoperc
>>> cat(demo, 'zoperc')
#!/bin/sh
<BLANKLINE>
# the next line is for chkconfig
# chkconfig: 345 90 10
# description: please, please work
<BLANKLINE>
<BLANKLINE>
if [ $(whoami) != "root" ]; then
  echo "You must be root."
  exit 1
fi
<BLANKLINE>
case $1 in
  stop)
<BLANKLINE>
    echo zope:
/demo/zope "$@" \
      </dev/null
<BLANKLINE>
    ;;
  restart)
<BLANKLINE>
    ${0} stop
    sleep 1
    ${0} start
<BLANKLINE>
    ;;
  *)
<BLANKLINE>
    echo zope:
/demo/zope "$@" \
      </dev/null
<BLANKLINE>
    ;;
esac
<BLANKLINE>

在这里我们只是调用现有的脚本。注意脚本中没有反映 env 或用户选项。当使用现有脚本时,假定它是完整的。

>>> import os
>>> os.remove(join(demo, 'zope'))

多个进程

有时,你需要启动多个进程。你可以指定多个部分。例如,假设我们想要启动 2 个 Zope 实例

>>> write('buildout.cfg',
... """
... [buildout]
... parts = zoperc
...
... [zoperc]
... recipe = zc.recipe.rhrc
... parts = instance1 instance2
... dest = %(dest)s
... chkconfig = 345 90 10
... chkconfigcommand = echo
... user = zope
...
... [instance1]
... run-script = /opt/zope/bin/zopectl -C /etc/instance1.conf
... env = LD_LIBRARY_PATH=/opt/foolib
...
... [instance2]
... """ % dict(dest=demo))
>>> write(demo, 'instance2', '')

注意对于实例 2,我们正在安排脚本已经存在。

>>> print system('bin/buildout'),
Uninstalling zoperc.
Running uninstall recipe.
--del zoperc
Installing zoperc.
--add zoperc
>>> cat(demo, 'zoperc')
#!/bin/sh
<BLANKLINE>
# the next line is for chkconfig
# chkconfig: 345 90 10
# description: please, please work
<BLANKLINE>
<BLANKLINE>
if [ $(whoami) != "root" ]; then
  echo "You must be root."
  exit 1
fi
<BLANKLINE>
case $1 in
  stop)
<BLANKLINE>
    echo instance2:
/demo/instance2 "$@" \
      </dev/null
<BLANKLINE>
    LD_LIBRARY_PATH=/opt/foolib \
      su zope -c \
      "/opt/zope/bin/zopectl -C /etc/instance1.conf $*" \
      </dev/null
<BLANKLINE>
    ;;
  restart)
<BLANKLINE>
    ${0} stop
    sleep 1
    ${0} start
<BLANKLINE>
    ;;
  *)
<BLANKLINE>
    LD_LIBRARY_PATH=/opt/foolib \
      su zope -c \
      "/opt/zope/bin/zopectl -C /etc/instance1.conf $*" \
      </dev/null
<BLANKLINE>
    echo instance2:
/demo/instance2 "$@" \
      </dev/null
<BLANKLINE>
    ;;
esac
<BLANKLINE>

现在 rc 脚本启动了这两个实例。注意它以相反的顺序停止它们。在这种情况下,这并不那么重要,但如果后面的脚本依赖于前面的脚本,那么这就会更加重要。

除了 zoperc 脚本之外,我们还获得了具有运行脚本选项的实例脚本

>>> ls(demo)
-  instance2
-  zoperc
-  zoperc-instance1
>>> cat(demo, 'zoperc-instance1')
#!/bin/sh
<BLANKLINE>
# This script is for adminstrator convenience.  It should
# NOT be installed as a system startup script!
<BLANKLINE>
<BLANKLINE>
if [ $(whoami) != "root" ]; then
  echo "You must be root."
  exit 1
fi
<BLANKLINE>
case $1 in
  stop)
<BLANKLINE>
    LD_LIBRARY_PATH=/opt/foolib \
      su zope -c \
      "/opt/zope/bin/zopectl -C /etc/instance1.conf $*"
<BLANKLINE>
    ;;
  restart)
<BLANKLINE>
    ${0} stop
    sleep 1
    ${0} start
<BLANKLINE>
    ;;
  *)
<BLANKLINE>
    LD_LIBRARY_PATH=/opt/foolib \
      su zope -c \
      "/opt/zope/bin/zopectl -C /etc/instance1.conf $*"
<BLANKLINE>
    ;;
esac
<BLANKLINE>

单个脚本没有 chkconfig 信息。

独立进程

通常,假定进程是相互依赖的,并且按顺序启动,按相反的顺序停止,在重启时,所有进程都停止然后全部启动。

如果使用独立进程选项,则生成的主运行脚本将把进程视为独立的,并分别重启处理。对于大量的独立进程,这可以减少单个进程关闭的时间。

>>> write('buildout.cfg',
... """
... [buildout]
... parts = zoperc
...
... [zoperc]
... recipe = zc.recipe.rhrc
... parts = instance1 instance2
... dest = %(dest)s
... chkconfig = 345 90 10
... chkconfigcommand = echo
... user = zope
... independent-processes = true
...
... [instance1]
... run-script = /opt/zope/bin/zopectl -C /etc/instance1.conf
... env = LD_LIBRARY_PATH=/opt/foolib
...
... [instance2]
... """ % dict(dest=demo))
>>> print system('bin/buildout'),
Uninstalling zoperc.
Running uninstall recipe.
--del zoperc
Installing zoperc.
--add zoperc
>>> cat(demo, 'zoperc')
#!/bin/sh
<BLANKLINE>
# the next line is for chkconfig
# chkconfig: 345 90 10
# description: please, please work
<BLANKLINE>
<BLANKLINE>
if [ $(whoami) != "root" ]; then
  echo "You must be root."
  exit 1
fi
<BLANKLINE>
    LD_LIBRARY_PATH=/opt/foolib \
      su zope -c \
      "/opt/zope/bin/zopectl -C /etc/instance1.conf $*" \
      </dev/null
<BLANKLINE>
    echo instance2:
/demo/instance2 "$@" \
      </dev/null

部署

zc.recipe.rhrc配方是为了与zc.recipe.deployment配方一起工作而设计的。您可以指定部署部分的名称。如果指定了部署部分,则

  • 部署名称将用于rc脚本

  • 如果rc脚本自己的部分中没有指定用户,则将使用部署部分中的用户。

  • 如果未指定目标,则将使用部署中的rc-directory选项。

    >>> write('buildout.cfg',
    ... """
    ... [buildout]
    ... parts = zoperc
    ...
    ... [deployment]
    ... name = acme
    ... user = acme
    ... rc-directory = %(dest)s
    ...
    ... [zoperc]
    ... recipe = zc.recipe.rhrc
    ... parts = instance1 instance2
    ... chkconfig = 345 90 10
    ... chkconfigcommand = echo
    ... deployment = deployment
    ...
    ... [instance1]
    ... run-script = /opt/zope/bin/zopectl -C /etc/instance1.conf
    ... env = LD_LIBRARY_PATH=/opt/foolib
    ...
    ... [instance2]
    ... """ % dict(dest=demo))
    

如果使用部署,则任何现有脚本都必须以部署名称为前缀。我们将重命名instance2脚本以反映这一点

>>> os.rename(join(demo, 'instance2'), join(demo, 'acme-instance2'))
>>> print system('bin/buildout'),
Uninstalling zoperc.
Running uninstall recipe.
--del zoperc
Installing zoperc.
--add acme
>>> ls(demo)
-  acme
-  acme-instance1
-  acme-instance2
>>> cat(demo, 'acme')
#!/bin/sh
<BLANKLINE>
# the next line is for chkconfig
# chkconfig: 345 90 10
# description: please, please work
<BLANKLINE>
<BLANKLINE>
if [ $(whoami) != "root" ]; then
  echo "You must be root."
  exit 1
fi
<BLANKLINE>
case $1 in
  stop)
<BLANKLINE>
    echo acme-instance2:
/demo/acme-instance2 "$@" \
      </dev/null
<BLANKLINE>
    LD_LIBRARY_PATH=/opt/foolib \
      su acme -c \
      "/opt/zope/bin/zopectl -C /etc/instance1.conf $*" \
      </dev/null
<BLANKLINE>
    ;;
  restart)
<BLANKLINE>
    ${0} stop
    sleep 1
    ${0} start
<BLANKLINE>
    ;;
  *)
<BLANKLINE>
    LD_LIBRARY_PATH=/opt/foolib \
      su acme -c \
      "/opt/zope/bin/zopectl -C /etc/instance1.conf $*" \
      </dev/null
<BLANKLINE>
    echo acme-instance2:
/demo/acme-instance2 "$@" \
      </dev/null
<BLANKLINE>
    ;;
esac
<BLANKLINE>

边缘情况,当我们删除部分时,我们卸载acme

>>> write('buildout.cfg',
... """
... [buildout]
... parts =
... """)
>>> print system('bin/buildout'),
Uninstalling zoperc.
Running uninstall recipe.
--del acme

进程管理

通常,该配方不会启动和停止进程。如果我们想让它这样做,我们可以使用带有“true”值的进程管理选项。

>>> write('buildout.cfg',
... """
... [buildout]
... parts = zoperc
...
... [zoperc]
... recipe = zc.recipe.rhrc
... parts = zope
... dest = %(dest)s
... process-management = true
...
... [zope]
... run-script = echo zope
... """ % dict(dest=demo))

当部分安装时,进程将被启动

>>> print system('bin/buildout'),
Installing zoperc.
zope start

当部分更新时,它也会被启动。这只是为了确保它在运行。

>>> print system('bin/buildout'),
Updating zoperc.
zope start

如果我们更新部分,那么当部分被卸载和重新安装时,进程将被停止和启动。我们通常会通过添加仅用于强制重新安装的摘要选项来强制这样做,通常是因为构建out中的其他某些内容已更改。

>>> write('buildout.cfg',
... """
... [buildout]
... parts = zoperc
...
... [zoperc]
... recipe = zc.recipe.rhrc
... parts = zope
... dest = %(dest)s
... process-management = true
... digest = 1
...
... [zope]
... run-script = echo zope
... """ % dict(dest=demo))
>>> print system('bin/buildout'),
Uninstalling zoperc.
Running uninstall recipe.
zope stop
Installing zoperc.
zope start
>>> print system('bin/buildout buildout:parts='),
Uninstalling zoperc.
Running uninstall recipe.
zope stop

回归测试

异常格式化错误

如果我们不提供运行脚本,我们会得到一个异常(错误:格式错误的异常字符串,包含字面量‘%s’)

>>> write('buildout.cfg',
... """
... [buildout]
... parts = zoperc
...
... [zoperc]
... recipe = zc.recipe.rhrc
... parts = zope
... dest = %(dest)s
...
... [zope]
... """ % dict(dest=demo))
>>> print system('bin/buildout'),
Installing zoperc.
zc.recipe.rhrc: Part zope doesn't define run-script and /demo/zope doesn't exist.
While:
  Installing zoperc.
Error: No script for zope

下载

项目详情


下载文件

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

源分发

zc.recipe.rhrc-1.4.2.tar.gz (16.8 kB 查看散列)

上传时间

由以下机构支持

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