如何在替换文件之前让puppet停止服务?

时间:2012-02-18 00:08:28

标签: puppet

在替换木偶服务背后的软件时,我试图避免竞争条件。

要做到这一点,puppet需要停止服务,替换可执行文件,然后启动服务。有没有办法让傀儡这样做?它的首选方式似乎是替换可执行文件,然后检查状态并在必要时再次启动服务。

(这个例子是人为的。真正的竞争条件远不是这么简单......)

这是我用来模拟这个问题的木偶清单:

$O = '1'
$I = '2'

exec { hi :
        command => '/bin/echo "$(/bin/date +%s) puppet says hello" >> /tmp/freebird.log' ,
        }

file { exe :
        name => "/tmp/freebird" ,
        ensure => present ,
        owner => "root" ,
        group => "root" ,
        mode => "0555" ,
        source => "/root/test-v$I" ,
        }

file { init :
        name => '/etc/init.d/freebird' ,
        ensure => present,
        owner => "root",
        group => "root",
        mode => "0555",
        source => "/root/test.init" ,
        }

service { freebird :
        ensure => running,
        enable => true,
        hasrestart => true,
        hasstatus => true,
        require => [ File[init], File[exe] ],
        }

这是 test-v1 文件。 test-v2 文件相同,但v=2

#!/bin/bash
v=1

while true
do
        echo "$(date +%s) $v" >> /tmp/freebird-v.log
        sleep 1
done

和init.d脚本:

#!/bin/bash
#
# /etc/rc.d/init.d/freebird

# chkconfig: 2345 90 10
# description:       freebird
# Provides:          freebird
# Required-Start:    $syslog $remote_fs
# Should-Start:
# Required-Stop:     $syslog $remote_fs
# Should-Stop:
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description:  freebird 


# Source function library.
. /etc/rc.d/init.d/functions

xme=freebird
export PATH=/sbin:/bin:/usr/sbin:/usr/bin

function L () {
        echo "$(date +%s) $*" 1>&2
        echo "$(date +%s) $*" >> /tmp/$xme.log
        }


case "$1" in
        (start) L $1 $xme
                ( /tmp/$xme &)
                ;;
        (stop) L $1 $xme
                fuser -k /tmp/$xme
                ;;
        (status) L $1 $xme
                /sbin/fuser /tmp/$xme >/dev/null 2>&1
                ;;
        (restart) L $1 $xme
                $0 stop
                $0 start
                ;;
        (*)
                echo "Usage: $xme {start|stop|status|restart]"
                exit 1
                ;;
esac

2 个答案:

答案 0 :(得分:2)

  

在替换木偶服务背后的软件时,我试图避免竞争条件。

     

要做到这一点,puppet需要停止服务,替换可执行文件,然后启动服务。有没有办法让傀儡这样做?它的首选方式似乎是替换可执行文件,然后检查状态并在必要时再次启动服务。

所以Puppet目前正在做的问题是它应该在替换某些文件后重新启动服务吗?

如果是这样,您应该使用通知/订阅关系,以便在替换文件后始终触发服务重新启动。以您的示例service为例,我们可以将订阅添加到构成它的文件中(与配置相同的方式),如果其中任何一个发生更改,这将触发重启。

service { freebird :
        ensure => running,
        enable => true,
        hasrestart => true,
        hasstatus => true,
        require => [ File[init], File[exe] ],
        subscribe => [ File[init], File[exe] ],
        }

另一种方法是使用您的操作系统包管理,Puppet对此有很好的支持。然后,您将从程序包脚本中触发重新启动(或在安装前/后安装中停止/启动),从而使Puppet确保服务已配置并正在运行。看看Jordan Sissel的fpm project是否可以轻松构建多种包格式。

答案 1 :(得分:1)

为了清晰和搜索,我会重新解释这个问题,然后提供解决方案。

我建议,如果您可以选择这样做,请使用原生包装系统的预安装功能。

问:如何通过puppet模拟rpm的预安装脚本。一个用例是在安装可执行文件之前停止puppet服务,然后在替换文件后再次启动它。这与puppet正常排序替换文件形成鲜明对比,然后重启服务。

幸运的是,我的用例已经需要符号链接。如果您没有,请发布您的解决方案。

要运行由以下文件组成的测试,我在 test.pp 中编辑$tversion,然后将其粘贴到我的终端中:

fuser /tmp/freebird-v.log /tmp/freebird
: > /tmp/freebird.log
echo ==== >> /tmp/freebird.log ; puppet apply --verbose --onetime --no-daemonize test.pp 2>&1 | tee ~/D ; cat /tmp/freebird.log
ps auxww|grep freebird
fuser /tmp/freebird-v.log /tmp/freebird

文件 test.pp

$tversion = '1'

exec { hi :
        command => '/bin/echo "$(/bin/date +%s) puppet says hello" >> /tmp/freebird.log' ,
        }

file { exe :
        name => "/tmp/freebird-v$tversion" ,
        ensure => present ,
        owner => "root" ,
        group => "root" ,
        mode => "0555" ,
        content => template("/root/test-template") ,
        }

file { exe_ln :
        name => "/tmp/freebird" ,
        ensure => link ,
        owner => "root" ,
        group => "root" ,
        mode => "0555" ,
        target => "/tmp/freebird-v$tversion" ,
        }

file { init :
        name => '/etc/init.d/freebird' ,
        ensure => present,
        owner => "root",
        group => "root",
        mode => "0555",
        source => "/root/test.init" ,
        }

exec { freebird_stop_if_incoherent :
        command => '/sbin/service freebird stop' ,
        refreshonly => false , # required for when entering at exe_ln
        onlyif => "/sbin/service freebird status && ! test /tmp/freebird -ef '/tmp/freebird-v$tversion'" , # short-circuits the refreshonly for most cases
        }

service { freebird :
        ensure => running,
        enable => true,
        hasrestart => true,
        hasstatus => true,
        }

File[exe_ln]            <~ Exec[freebird_stop_if_incoherent]
Service[freebird]       <- File[exe_ln]

文件测试模板

#!/bin/bash
v=<%= tversion %>

while true
do
        echo "$(date +%s) $v" >> /tmp/freebird-v.log
        sleep 1
done

文件 test.init

#!/bin/bash
#
# /etc/rc.d/init.d/freebird

# chkconfig: 2345 90 10
# description:       freebird
# Provides:          freebird
# Required-Start:    $syslog $remote_fs
# Should-Start:
# Required-Stop:     $syslog $remote_fs
# Should-Stop:
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description:  freebird 


# Source function library.
. /etc/rc.d/init.d/functions

xme=freebird
export PATH=/sbin:/bin:/usr/sbin:/usr/bin

function L () {
        local pid=$$
        local ppid=$(ps l $pid |awk '{print $4}' |tail -1)
        local extra="-- $(ps $ppid|tail -1|sed 's,^[^/]*/,/, ; s,/[0-9][^/]*/,/,')"
        echo "$(date +%s) $pid $ppid $* $extra" 1>&2
        echo "$(date +%s) $pid $ppid $* $extra" >>/tmp/$xme.log 2>&1
        }


case "$1" in
        (start) L $1 $xme
                fuser /tmp/$xme >/dev/null 2>&1 || ( /tmp/$xme &)
                ;;
        (stop) L $1 $xme
                fuser /tmp/$xme 2>&1
                fuser -k /tmp/$xme 1>&2 ||true
                fuser /tmp/$xme 2>&1
                true
                ;;
        (status) L $1 $xme
                /sbin/fuser /tmp/$xme >/dev/null 2>&1
                ;;
        (restart) L $1 $xme
                fuser -k /tmp/$xme 1>&2 ||true
                ( /tmp/$xme &)
                ;;
        (*)
                echo "Usage: $xme {start|stop|status|restart]"
                exit 1
                ;;
esac