2012-02-18 61 views
6

我試圖在更換傀儡服務後面的軟件時避免競爭狀況。如何在替換文件之前讓木偶停止服務?

要做到這一點,木偶需要停止服務,更換的可執行文件,然後開始服務。有沒有辦法讓傀儡這樣做?它的首選做法似乎是替換可執行文件,然後檢查狀態並在必要時再次啓動服務。

(這個例子是人爲真正的競爭條件是隔靴搔癢這個簡單的...)

這裏的木偶清單我使用來模擬這個問題:

$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

我想更換軟件的傀儡服務落後時,爲了避免競爭條件。

爲此,puppet需要停止服務,替換可執行文件,然後啓動服務。有沒有辦法讓傀儡這樣做?它的首選做法似乎是替換可執行文件,然後檢查狀態並在必要時再次啓動服務。

所以Puppet目前所做的問題是它應該總是在替換某些文件後重新啓動服務?

如果是這樣,您應該使用通知/訂閱關係來在文件被替換後始終觸發服務重新啓動。以您的示例service爲例,我們可以將訂閱添加到構成它的文件上(與使用配置的方式相同),如果它們中的任何一個發生更改,則會觸發重新啓動。

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

這樣做的另一種方式是使用OS包管理,這是Puppet的良好支持。然後,您將從軟件包腳本中觸發重新啓動(或者在安裝前/安裝後停止/啓動),從而使Puppet確保服務已配置並正在運行。看看喬丹Sissel的fpm project爲一個工具,可以輕鬆地構建許多包格式。

+0

M0dlx,謝謝。您的評論將我推向了正確的道路。 如果我要從頭開始,我肯定會使用操作系統打包程序的預安裝功能,而不是強制puppet來處理這個問題。和fpm使得更容易... – bugi 2012-02-22 00:57:09

+0

@ m0dlx,我有一個疑問。如果我的清單類似於File ['X'],File ['Y'],File ['Z'] - > Service ['XYZ'] {subscribe:File ['X','Y']}' ?只有在創建了'file'Z''後,服務纔會被執行/重新啓動,否則每當'file X/Y/Z'被修改時它就會重新啓動。 – harshad 2015-12-07 05:31:30

1

爲了清楚起見和搜索,我將重新解釋這個問題,然後提供一個解決方案。

但是,我會建議,如果您可以選擇這樣做,請使用本機打包系統的預安裝功能。

問:如何通過puppet模擬rpm的預安裝腳本。一個用例是在安裝可執行文件之前停止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