class Puppet::Daemon

Run periodic actions and a network server in a daemonized process.

A Daemon has 3 parts:

* config reparse
* (optional) an agent that responds to #run
* (optional) a server that response to #stop, #start, and #wait_for_shutdown

The config reparse will occur periodically based on Settings. The server will be started and is expected to manage its own run loop (and so not block the start call). The server will, however, still be waited for by using the wait_for_shutdown method. The agent is run periodically and a time interval based on Settings. The config reparse will update this time interval when needed.

The Daemon is also responsible for signal handling, starting, stopping, running the agent on demand, and reloading the entire process. It ensures that only one Daemon is running by using a lockfile.

@api private

Constants

SIGNAL_CHECK_INTERVAL

Attributes

agent[RW]
argv[RW]
server[RW]
signals[R]

Public Instance Methods

close_streams() click to toggle source

Convenience signature for calling ::close_streams

# File lib/puppet/daemon.rb, line 77
def close_streams()
  Puppet::Daemon.close_streams
end
daemonize() click to toggle source

Put the daemon into the background.

# File lib/puppet/daemon.rb, line 40
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("/")

  close_streams
end
daemonname() click to toggle source
# File lib/puppet/daemon.rb, line 35
def daemonname
  Puppet.run_mode.name
end
reexec() click to toggle source
# File lib/puppet/daemon.rb, line 81
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() click to toggle source
# File lib/puppet/daemon.rb, line 89
def reload
  return unless agent
  if agent.running?
    Puppet.notice "Not triggering already-running agent"
    return
  end

  agent.run({:splay => false})
end
reopen_logs() click to toggle source
# File lib/puppet/daemon.rb, line 104
def reopen_logs
  Puppet::Util::Log.reopen
end
restart() click to toggle source
# File lib/puppet/daemon.rb, line 99
def restart
  Puppet::Application.restart!
  reexec unless agent and agent.running?
end
set_signal_traps() click to toggle source

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.

# File lib/puppet/daemon.rb, line 110
def set_signal_traps
  [:INT, :TERM].each do |signal|
    Signal.trap(signal) do
      Puppet.notice "Caught #{signal}; exiting"
      stop
    end
  end

  # extended signals not supported under windows
  if !Puppet.features.microsoft_windows?
    signals = {:HUP => :restart, :USR1 => :reload, :USR2 => :reopen_logs }
    signals.each do |signal, method|
      Signal.trap(signal) do
        Puppet.notice "Caught #{signal}; storing #{method}"
        @signals << method
      end
    end
  end
end
start() click to toggle source
# File lib/puppet/daemon.rb, line 143
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

  server.wait_for_shutdown if server
end
stop(args = {:exit => true}) click to toggle source

Stop everything

# File lib/puppet/daemon.rb, line 131
def stop(args = {:exit => true})
  Puppet::Application.stop!

  server.stop if server

  remove_pidfile

  Puppet::Util::Log.close_all

  exit if args[:exit]
end

Public Class Methods

close_streams() click to toggle source

Close stdin/stdout/stderr so that we can finish our transition into ‘daemon’ mode. @return nil

# File lib/puppet/daemon.rb, line 59
def self.close_streams()
  Puppet.debug("Closing streams for daemon mode")
  begin
    $stdin.reopen "/dev/null"
    $stdout.reopen "/dev/null", "a"
    $stderr.reopen $stdout
    Puppet::Util::Log.reopen
    Puppet.debug("Finished closing streams for daemon mode")
  rescue => detail
    Puppet.err "Could not start #{Puppet.run_mode.name}: #{detail}"
    Puppet::Util::replace_file("/tmp/daemonout", 0644) do |f|
      f.puts "Could not start #{Puppet.run_mode.name}: #{detail}"
    end
    exit(12)
  end
end
new(pidfile, scheduler = Puppet::Scheduler::Scheduler.new()) click to toggle source
# File lib/puppet/daemon.rb, line 29
def initialize(pidfile, scheduler = Puppet::Scheduler::Scheduler.new())
  @scheduler = scheduler
  @pidfile = pidfile
  @signals = []
end