/usr/lib/ruby/vendor_ruby/chef/expander/daemonizable.rb is in chef-expander 10.12.0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | #
# Author:: Daniel DeLeo (<dan@opscode.com>)
# Copyright:: Copyright (c) 2011 Opscode, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require 'etc'
require 'chef/expander/loggable'
module Chef
module Expander
class AlreadyRunning < RuntimeError
end
class NoSuchUser < ArgumentError
end
class NoSuchGroup < ArgumentError
end
module Daemonizable
include Loggable
# Daemonizes the process if configured to do so, and ensures that only one
# copy of the process is running with a given config by obtaining an
# exclusive lock on the pidfile. Also sets process user and group if so
# configured.
# ===Raises
# * AlreadyRunning::: when another process has the exclusive lock on the pidfile
# * NoSuchUser::: when a user is configured that doesn't exist
# * NoSuchGroup::: when a group is configured that doesn't exist
# * SystemCallError::: if there is an error creating the pidfile
def configure_process
Expander.config.daemonize? ? daemonize : ensure_exclusive
set_user_and_group
end
def daemonize
acquire_locks
exit if fork
Process.setsid
exit if fork
write_pid
Dir.chdir('/')
STDIN.reopen("/dev/null")
STDOUT.reopen("/dev/null", "a")
STDERR.reopen("/dev/null", "a")
end
# When not forking into the background, this ensures only one chef-expander
# is running with a given config and writes the process id to the pidfile.
def ensure_exclusive
acquire_locks
write_pid
end
def set_user_and_group
return nil if Expander.config.user.nil?
if Expander.config.group.nil?
log.info {"Changing user to #{Expander.config.user}"}
else
log.info {"Changing user to #{Expander.config.user} and group to #{Expander.config.group}"}
end
unless (set_group && set_user)
log.error {"Unable to change user to #{Expander.config.user} - Are you root?"}
end
end
# Deletes the pidfile, releasing the exclusive lock on it in the process.
def release_locks
File.unlink(@pidfile.path) if File.exist?(@pidfile.path)
@pidfile.close unless @pidfile.closed?
end
private
def set_user
Process::Sys.setuid(target_uid)
true
rescue Errno::EPERM => e
log.debug {e}
false
end
def set_group
if gid = target_uid
Process::Sys.setgid(gid)
end
true
rescue Errno::EPERM
log.debug {e}
false
end
def target_uid
user = Expander.config.user
user.kind_of?(Fixnum) ? user : Etc.getpwnam(user).uid
rescue ArgumentError => e
log.debug {e}
raise NoSuchUser, "Cannot change user to #{user} - failed to find the uid"
end
def target_gid
if group = Expander.config.group
group.kind_of?(Fixnum) ? group : Etc.getgrnam(group).gid
else
nil
end
rescue ArgumentError => e
log.debug {e}
raise NoSuchGroup, "Cannot change group to #{group} - failed to find the gid"
end
def acquire_locks
@pidfile = File.open(Expander.config.pidfile, File::RDWR|File::CREAT, 0644)
unless @pidfile.flock(File::LOCK_EX | File::LOCK_NB)
pid = @pidfile.read.strip
msg = "Another instance of chef-expander (pid: #{pid}) has a lock on the pidfile (#{Expander.config.pidfile}). \n"\
"Configure a different pidfile to run multiple instances of chef-expander at once."
raise AlreadyRunning, msg
end
rescue Exception
@pidfile.close if @pidfile && !@pidfile.closed?
raise
end
def write_pid
@pidfile.truncate(0)
@pidfile.print("#{Process.pid}\n")
@pidfile.flush
end
end
end
end
|