Class: Puppet::Daemon
Overview
A module that handles operations common to all daemons. This is included into the Server and Client base classes.
Instance Attribute Summary collapse
-
#agent ⇒ Object
Returns the value of attribute agent.
-
#argv ⇒ Object
Returns the value of attribute argv.
-
#server ⇒ Object
Returns the value of attribute server.
Instance Method Summary collapse
-
#create_pidfile ⇒ Object
Create a pidfile for our daemon, so we can be stopped and others don’t try to start.
-
#daemonize ⇒ Object
Put the daemon into the background.
- #daemonname ⇒ Object
-
#pidfile ⇒ Object
Provide the path to our pidfile.
- #reexec ⇒ Object
- #reload ⇒ Object
-
#remove_pidfile ⇒ Object
Remove the pid file for our daemon.
- #reopen_logs ⇒ Object
- #restart ⇒ Object
- #run_event_loop ⇒ Object
-
#set_signal_traps ⇒ Object
Trap a couple of the main signals.
- #start ⇒ Object
-
#stop(args = {:exit => true}) ⇒ Object
Stop everything.
Instance Attribute Details
#agent ⇒ Object
Returns the value of attribute agent.
8 9 10 |
# File 'lib/vendor/puppet/daemon.rb', line 8 def agent @agent end |
#argv ⇒ Object
Returns the value of attribute argv.
8 9 10 |
# File 'lib/vendor/puppet/daemon.rb', line 8 def argv @argv end |
#server ⇒ Object
Returns the value of attribute server.
8 9 10 |
# File 'lib/vendor/puppet/daemon.rb', line 8 def server @server end |
Instance Method Details
#create_pidfile ⇒ Object
Create a pidfile for our daemon, so we can be stopped and others don’t try to start.
44 45 46 47 48 |
# File 'lib/vendor/puppet/daemon.rb', line 44 def create_pidfile Puppet::Util.synchronize_on(Puppet[:name],Sync::EX) do raise "Could not create PID file: #{pidfile}" unless Puppet::Util::Pidlock.new(pidfile).lock end end |
#daemonize ⇒ Object
Put the daemon into the background.
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 |
# File 'lib/vendor/puppet/daemon.rb', line 15 def daemonize if pid = fork Process.detach(pid) exit(0) end create_pidfile # Get rid of console logging Puppet::Util::Log.close(:console) Process.setsid Dir.chdir("/") begin $stdin.reopen "/dev/null" $stdout.reopen "/dev/null", "a" $stderr.reopen $stdout Puppet::Util::Log.reopen rescue => detail Puppet.err "Could not start #{Puppet[:name]}: #{detail}" Puppet::Util::replace_file("/tmp/daemonout", 0644) do |f| f.puts "Could not start #{Puppet[:name]}: #{detail}" end exit(12) end end |
#daemonname ⇒ Object
10 11 12 |
# File 'lib/vendor/puppet/daemon.rb', line 10 def daemonname Puppet[:name] end |
#pidfile ⇒ Object
Provide the path to our pidfile.
51 52 53 |
# File 'lib/vendor/puppet/daemon.rb', line 51 def pidfile Puppet[:pidfile] end |
#reexec ⇒ Object
55 56 57 58 59 60 61 |
# File 'lib/vendor/puppet/daemon.rb', line 55 def reexec raise Puppet::DevError, "Cannot reexec unless ARGV arguments are set" unless argv command = $0 + " " + argv.join(" ") Puppet.notice "Restarting with '#{command}'" stop(:exit => false) exec(command) end |
#reload ⇒ Object
63 64 65 66 67 68 69 70 71 |
# File 'lib/vendor/puppet/daemon.rb', line 63 def reload return unless agent if agent.running? Puppet.notice "Not triggering already-running agent" return end agent.run end |
#remove_pidfile ⇒ Object
Remove the pid file for our daemon.
74 75 76 77 78 |
# File 'lib/vendor/puppet/daemon.rb', line 74 def remove_pidfile Puppet::Util.synchronize_on(Puppet[:name],Sync::EX) do Puppet::Util::Pidlock.new(pidfile).unlock end end |
#reopen_logs ⇒ Object
85 86 87 |
# File 'lib/vendor/puppet/daemon.rb', line 85 def reopen_logs Puppet::Util::Log.reopen end |
#restart ⇒ Object
80 81 82 83 |
# File 'lib/vendor/puppet/daemon.rb', line 80 def restart Puppet::Application.restart! reexec unless agent and agent.running? end |
#run_event_loop ⇒ Object
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'lib/vendor/puppet/daemon.rb', line 130 def run_event_loop # Now, we loop waiting for either the configuration file to change, or the # next agent run to be due. Fun times. # # We want to trigger the reparse if 15 seconds passed since the previous # wakeup, and the agent run if Puppet[:runinterval] seconds have passed # since the previous wakeup. # # We always want to run the agent on startup, so it was always before now. # Because 0 means "continuously run", `to_i` does the right thing when the # input is strange or badly formed by returning 0. Integer will raise, # which we don't want, and we want to protect against -1 or below. next_agent_run = 0 agent_run_interval = [Puppet[:runinterval].to_i, 0].max # We may not want to reparse; that can be disable. Fun times. next_reparse = 0 reparse_interval = Puppet[:filetimeout].to_i loop do now = Time.now.to_i # We set a default wakeup of "one hour from now", which will # recheck everything at a minimum every hour. Just in case something in # the math messes up or something; it should be inexpensive enough to # wake once an hour, then go back to sleep after doing nothing, if # someone only wants listen mode. next_event = now + 60 * 60 # Handle reparsing of configuration files, if desired and required. # `reparse` will just check if the action is required, and would be # better named `reparse_if_changed` instead. if reparse_interval > 0 and now >= next_reparse Puppet.settings.reparse # The time to the next reparse might have changed, so recalculate # now. That way we react dynamically to reconfiguration. reparse_interval = Puppet[:filetimeout].to_i # Set up the next reparse check based on the new reparse_interval. if reparse_interval > 0 next_reparse = now + reparse_interval next_event > next_reparse and next_event = next_reparse end # We should also recalculate the agent run interval, and adjust the # next time it is scheduled to run, just in case. In the event that # we made no change the result will be a zero second adjustment. new_run_interval = [Puppet[:runinterval].to_i, 0].max next_agent_run += agent_run_interval - new_run_interval agent_run_interval = new_run_interval end # Handle triggering another agent run. This will block the next check # for configuration reparsing, which is a desired and deliberate # behaviour. You should not change that. --daniel 2012-02-21 if agent and now >= next_agent_run agent.run # Set up the next agent run time next_agent_run = now + agent_run_interval next_event > next_agent_run and next_event = next_agent_run end # Finally, an interruptable able sleep until the next scheduled event. how_long = next_event - now how_long > 0 and select([], [], [], how_long) end end |
#set_signal_traps ⇒ Object
Trap a couple of the main signals. This should probably be handled in a way that anyone else can register callbacks for traps, but, eh.
91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/vendor/puppet/daemon.rb', line 91 def set_signal_traps signals = {:INT => :stop, :TERM => :stop } # extended signals not supported under windows signals.update({:HUP => :restart, :USR1 => :reload, :USR2 => :reopen_logs }) unless Puppet.features.microsoft_windows? signals.each do |signal, method| Signal.trap(signal) do Puppet.notice "Caught #{signal}; calling #{method}" send(method) end end end |
#start ⇒ Object
116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/vendor/puppet/daemon.rb', line 116 def start set_signal_traps create_pidfile raise Puppet::DevError, "Daemons must have an agent, server, or both" unless agent or server # Start the listening server, if required. server.start if server # Finally, loop forever running events - or, at least, until we exit. run_event_loop end |