6

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

为此,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
4

2 回答 2

2

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

为此,puppet 需要停止服务,替换可执行文件,然后启动服务。有没有办法说服 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 项目,了解一种可以轻松构建多种包格式的工具。

于 2012-02-18T07:54:25.497 回答
1

为了清晰和搜索,我将重新表述问题,然后提供解决方案。

但是,我建议,如果您可以选择这样做,请使用本机打包系统的预安装功能。

问:如何通过 puppet 模拟 rpm 的预安装脚本。一种用例是在安装可执行文件之前停止 puppet 服务,然后在替换文件后再次启动它。这与 puppet 的替换文件的正常顺序相反,然后重新启动服务。

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

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

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
于 2012-02-22T00:56:28.243 回答