Class: Backdat::Daemon

Inherits:
Object
  • Object
show all
Defined in:
lib/backdat/daemon.rb

Overview

Daemon helper routines.

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.nameObject

Returns the value of attribute name.



6
7
8
# File 'lib/backdat/daemon.rb', line 6

def name
  @name
end

Class Method Details

._change_privilege(user, group = user) ⇒ Object

Note:

The group parameter defaults to user unless specified.

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

Parameters:

  • user (String)

    The user to change the process to.

  • group (String) (defaults to: user)

    The group to change the process to.



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
151
152
153
# File 'lib/backdat/daemon.rb', line 122

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
    Backdat::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
    Backdat::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}"
  Backdat::Application.fatal!(msg)
end

.change_privilegeObject

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



100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/backdat/daemon.rb', line 100

def change_privilege
  Dir.chdir("/")

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

.daemonize(name) ⇒ Object

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

Parameters:

  • name (String)

    The name to be used for the pid file



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/backdat/daemon.rb', line 11

def daemonize(name)
  @name = name
  pid = pid_from_file
  unless running?
    remove_pid_file()
    Backdat::Log.info("Daemonizing...")
    begin
      exit if fork; Process.setsid; exit if fork
      msg =  "Forked, in #{Process.pid}. "
      msg << "Privileges: #{Process.euid} #{Process.egid}"
      Backdat::Log.info(msg)
      File.umask Backdat::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
      Backdat::Application.fatal!("There is no fork: #{e.message}")
    end
  else
    Backdat::Application.fatal!("Backdat is already running pid #{pid}")
  end
end

.pid_fileString

Gets the pid file for @name.

Returns:

  • (String)

    Location of the pid file for @name.



57
58
59
# File 'lib/backdat/daemon.rb', line 57

def pid_file
   Backdat::Config[:pid_file] or "/tmp/#{@name}.pid"
end

.pid_from_fileFixnum, NilClass

Sucks the pid out of pid_file.

Returns:

  • (Fixnum, NilClass)

    The PID from pid_file or nil if it doesn’t exist.



64
65
66
67
68
# File 'lib/backdat/daemon.rb', line 64

def pid_from_file
  File.read(pid_file).chomp.to_i
rescue Errno::ENOENT, Errno::EACCES
  nil
end

.remove_pid_fileObject

Delete the PID from the filesystem



95
96
97
# File 'lib/backdat/daemon.rb', line 95

def remove_pid_file
  FileUtils.rm(pid_file) if File.exists?(pid_file)
end

.running?true, false

Checks if Backdat is running based on the pid_file.

Returns:

  • (true, false)

    Whether or not Backdat is running.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/backdat/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}"
  Backdat::Application.fatal!(msg)
end

.save_pid_fileObject

Note:

This uses the Backdat::Config option or “/tmp/name.pid” by default.

Store the PID on the filesystem.



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/backdat/daemon.rb', line 75

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}"
    Backdat::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}"
    Backdat::Application.fatal!(msg)
  end
end