class Souffle::Daemon

Daemon helper routines.

Attributes

name[RW]

Public Class Methods

_change_privilege(user, group=user) click to toggle source

Change privileges of the process to be the specified user and group

@param [ String ] user The user to change the process to. @param [ String ] group The group to change the process to.

@note

The group parameter defaults to user unless specified.
# File lib/souffle/daemon.rb, line 123
def _change_privilege(user, group=user)
  uid, gid = Process.euid, Process.egid

  begin
    target_uid = Etc.getpwnam(user).uid
  rescue ArgumentError => e
    msg =  "Failed to get UID for user #{user}, does it exist? "
    msg << e.message
    Souffle::Application.fatal!(msg)
    return false
  end
 
  begin
    target_gid = Etc.getgrnam(group).gid
  rescue ArgumentError => e
    msg =  "Failed to get GID for group #{group}, does it exist? "
    msg << e.message
    Souffle::Application.fatal!(msg)
    return false
  end

  if (uid != target_uid) or (gid != target_gid)
    Process.initgroups(user, target_gid)
    Process::GID.change_privilege(target_gid)
    Process::UID.change_privilege(target_uid)
  end
  true
rescue Errno::EPERM => e
  msg =  "Permission denied when trying to change #{uid}:#{gid} "
  msg << "to #{target_uid}:#{target_gid}. #{e.message}"
  Souffle::Application.fatal!(msg)
end
change_privilege() click to toggle source

Change process user/group to those specified in Souffle::Config

# File lib/souffle/daemon.rb, line 101
def change_privilege
  Dir.chdir("/")

  msg =  "About to change privilege to "
  if Souffle::Config[:user] and Souffle::Config[:group]
    msg << "#{Souffle::Config[:user]}:#{Souffle::Config[:group]}"
    Souffle::Log.info(msg)
    _change_privilege(Souffle::Config[:user], Souffle::Config[:group])
  elsif Souffle::Config[:user]
    msg << "#{Souffle::Config[:user]}"
    Souffle::Log.info(msg)
    _change_privilege(Souffle::Config[:user])
  end
end
daemonize(name) click to toggle source

Daemonize the current process, managing pidfiles and process uid/gid.

@param [ String ] name The name to be used for the pid file

# File lib/souffle/daemon.rb, line 11
def daemonize(name)
  @name = name
  pid = pid_from_file
  unless running?
    remove_pid_file()
    Souffle::Log.info("Daemonizing...")
    begin
      exit if fork; Process.setsid; exit if fork
      msg =  "Forked, in #{Process.pid}. "
      msg << "Privileges: #{Process.euid} #{Process.egid}"
      Souffle::Log.info(msg)
      File.umask Souffle::Config[:umask]
      $stdin.reopen("/dev/null")
      $stdout.reopen("/dev/null", "a")
      $stderr.reopen($stdout)
      save_pid_file;
      at_exit { remove_pid_file }
    rescue NotImplementedError => e
      Souffle::Application.fatal!("There is no fork: #{e.message}")
    end
  else
    Souffle::Application.fatal!("Souffle is already running pid #{pid}")
  end
end
pid_file() click to toggle source

Gets the pid file for @name.

@return [ String ] Location of the pid file for @name.

# File lib/souffle/daemon.rb, line 57
def pid_file
   Souffle::Config[:pid_file] or "/tmp/#{@name}.pid"
end
pid_from_file() click to toggle source

Sucks the pid out of pid_file.

@return [ Fixnum,NilClass ] The PID from pid_file or nil if it doesn't exist.

# File lib/souffle/daemon.rb, line 65
def pid_from_file
  File.read(pid_file).chomp.to_i
rescue Errno::ENOENT, Errno::EACCES
  nil
end
remove_pid_file() click to toggle source

Delete the PID from the filesystem

# File lib/souffle/daemon.rb, line 96
def remove_pid_file
  FileUtils.rm(pid_file) if File.exists?(pid_file)
end
running?() click to toggle source

Checks if Souffle is running based on the pid_file.

@return [ Boolean ] Whether or not Souffle is running.

# File lib/souffle/daemon.rb, line 39
def running?
  if pid_from_file.nil?
    false
  else
    Process.kill(0, pid_from_file)
    true
  end
rescue Errno::ESRCH, Errno::ENOENT
  false
rescue Errno::EACCES => e
  msg =  "You don't have access to the PID "
  msg << "file at #{pid_file}: #{e.message}"
  Souffle::Application.fatal!(msg)
end
save_pid_file() click to toggle source

Store the PID on the filesystem.

@note

This uses the Souffle::Config[:pid_file] option or "/tmp/name.pid"
by default.
# File lib/souffle/daemon.rb, line 76
def save_pid_file
  file = pid_file
  begin
    FileUtils.mkdir_p(File.dirname(file))
  rescue Errno::EACCES => e
    msg =  "Failed store pid in #{File.dirname(file)}, "
    msg << "permission denied: #{e.message}"
    Souffle::Application.fatal!(msg)
  end

  begin
    File.open(file, "w") { |f| f.write(Process.pid.to_s) }
  rescue Errno::EACCES => e
    msg =  "Couldn't write to pidfile #{file}, "
    msg << "permission denied: #{e.message}"
    Souffle::Application.fatal!(msg)
  end
end