How can I make a puppet terminate a service before replacing a file?

I try to avoid a race condition when replacing software behind a puppet service.

To do this, the puppet must stop the service, replace the executable file, and then start the service. Is there any way to talk to a puppet? His preferred way of doing things seems to be to replace the executable, then check the status and restart the service if necessary.

(This example is contrived. The state of a real race never comes close to this simple ...)

Here is the puppet manifest that I use to simulate this problem:

$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] ], } 

Here is the test-v1 file. The test-v2 file is the same, but with v=2 .

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

And init.d script:

 #!/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 
+6
source share
2 answers

I try to avoid a race condition when replacing software behind a puppet service.

To do this, the puppet must stop the service, replace the executable file, and then start the service. Is there any way to talk to a puppet? His preferred way of doing things seems to be to replace the executable, then check the status and restart the service if necessary.

So, the problem with what Puppet is doing right now is that it should always restart the service after replacing certain files?

If so, you should use the notification / subscription relationship to always start restarting the service after replacing files. Taking your service example, we can add subscriptions to the files that create it (the same as with the configuration), and this will restart if any of them change.

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

Another way to do this is to use OS package management, which Puppet has good support for. You then start a restart (or stop / start in pre / post installation) from the package scripts, leaving Puppet to ensure that the service is configured and started. Take a look at the Jordan Sissel fpm project for a tool that can easily create many package formats.

+2
source

I will rephrase the question for clarity and search, and then provide a solution.

I would suggest, however, that if you have the opportunity to do this, use the pre-installation function of your own packaging system.

Q: How to emulate rpm before installing the script through the puppet. One use case is to stop the puppet service before installing the executable, and then run it again after replacing the file. This is contrary to the normal puppet file replacement order, and then restart the service.

Fortunately, my use case already requires a mess of symbolic links. If you do not, submit your decision.

To run a test consisting of the files below, I edit $tversion in test.pp and paste it into my terminal:

 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 

File 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] 

File template file:

 #!/bin/bash v=<%= tversion %> while true do echo "$(date +%s) $v" >> /tmp/freebird-v.log sleep 1 done 

File 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 
+1
source

Source: https://habr.com/ru/post/908749/


All Articles