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
|
Puppet::Type.type(:service).provide :base, :parent => :service do
desc "The simplest form of Unix service support.
You have to specify enough about your service for this to work; the
minimum you can specify is a binary for starting the process, and this
same binary will be searched for in the process table to stop the
service. As with `init`-style services, it is preferable to specify start,
stop, and status commands.
"
commands :kill => "kill"
# get the proper 'ps' invocation for the platform
# ported from the facter 2.x implementation, since facter 3.x
# is dropping the fact (for which this was the only use)
def getps
case Puppet.runtime[:facter].value(:operatingsystem)
when 'OpenWrt'
'ps www'
when 'FreeBSD', 'NetBSD', 'OpenBSD', 'Darwin', 'DragonFly'
'ps auxwww'
else
'ps -ef'
end
end
private :getps
# Get the process ID for a running process. Requires the 'pattern'
# parameter.
def getpid
@resource.fail "Either stop/status commands or a pattern must be specified" unless @resource[:pattern]
regex = Regexp.new(@resource[:pattern])
ps = getps
self.debug "Executing '#{ps}'"
table = Puppet::Util::Execution.execute(ps)
# The output of the PS command can be a mashup of several different
# encodings depending on which processes are running and what
# arbitrary data has been used to set their name in the process table.
#
# First, try a polite conversion to in order to match the UTF-8 encoding
# of our regular expression.
table = Puppet::Util::CharacterEncoding.convert_to_utf_8(table)
# If that fails, force to UTF-8 and then scrub as most uses are scanning
# for ACII-compatible program names.
table.force_encoding(Encoding::UTF_8) unless table.encoding == Encoding::UTF_8
table = table.scrub unless table.valid_encoding?
table.each_line { |line|
if regex.match(line)
self.debug "Process matched: #{line}"
ary = line.sub(/^[[:space:]]+/u, '').split(/[[:space:]]+/u)
return ary[1]
end
}
nil
end
private :getpid
# Check if the process is running. Prefer the 'status' parameter,
# then 'statuscmd' method, then look in the process table. We give
# the object the option to not return a status command, which might
# happen if, for instance, it has an init script (and thus responds to
# 'statuscmd') but does not have 'hasstatus' enabled.
def status
if @resource[:status] or statuscmd
# Don't fail when the exit status is not 0.
status = service_command(:status, false)
# Explicitly calling exitstatus to facilitate testing
if status.exitstatus == 0
return :running
else
return :stopped
end
else
pid = getpid
if pid
self.debug "PID is #{pid}"
return :running
else
return :stopped
end
end
end
# There is no default command, which causes other methods to be used
def statuscmd
end
# Run the 'start' parameter command, or the specified 'startcmd'.
def start
service_command(:start)
nil
end
# The command used to start. Generated if the 'binary' argument
# is passed.
def startcmd
if @resource[:binary]
return @resource[:binary]
else
raise Puppet::Error,
"Services must specify a start command or a binary"
end
end
# Stop the service. If a 'stop' parameter is specified, it
# takes precedence; otherwise checks if the object responds to
# a 'stopcmd' method, and if so runs that; otherwise, looks
# for the process in the process table.
# This method will generally not be overridden by submodules.
def stop
if @resource[:stop] or stopcmd
service_command(:stop)
nil
else
pid = getpid
unless pid
self.info _("%{name} is not running") % { name: self.name }
return false
end
begin
output = kill pid
rescue Puppet::ExecutionFailure
@resource.fail Puppet::Error, "Could not kill #{self.name}, PID #{pid}: #{output}", $!
end
return true
end
end
# There is no default command, which causes other methods to be used
def stopcmd
end
end
|