Class: God::Process

Inherits:
Object
  • Object
show all
Defined in:
lib/god/process.rb

Constant Summary collapse

WRITES_PID =
[:start, :restart]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Process

Returns a new instance of Process.



9
10
11
12
13
14
15
# File 'lib/god/process.rb', line 9

def initialize(options={})
  options.each do |k,v|
    send("#{k}=", v)
  end
  
  @tracking_pid = false
end

Instance Attribute Details

#gidObject

Returns the value of attribute gid.



7
8
9
# File 'lib/god/process.rb', line 7

def gid
  @gid
end

#nameObject

Returns the value of attribute name.



7
8
9
# File 'lib/god/process.rb', line 7

def name
  @name
end

#restartObject

Returns the value of attribute restart.



7
8
9
# File 'lib/god/process.rb', line 7

def restart
  @restart
end

#startObject

Returns the value of attribute start.



7
8
9
# File 'lib/god/process.rb', line 7

def start
  @start
end

#stopObject

Returns the value of attribute stop.



7
8
9
# File 'lib/god/process.rb', line 7

def stop
  @stop
end

#uidObject

Returns the value of attribute uid.



7
8
9
# File 'lib/god/process.rb', line 7

def uid
  @uid
end

Instance Method Details

#call_action(action) ⇒ Object



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
# File 'lib/god/process.rb', line 44

def call_action(action)
  command = send(action)
  if command.kind_of?(String)
    # Make pid directory
    unless test(?d, God.pid_file_directory)
      begin
        FileUtils.mkdir_p(God.pid_file_directory)
      rescue Errno::EACCES => e
        abort"Failed to create pid file directory: #{e.message}"
      end
    end
    
    unless test(?w, God.pid_file_directory)
      abort "The pid file directory (#{God.pid_file_directory}) is not writable by #{Etc.getlogin}"
    end
    
    # string command
    # fork/exec to setuid/gid
    r, w = IO.pipe
    opid = fork do
      STDOUT.reopen(w)
      r.close
      pid = fork do
        ::Process.setsid
        ::Process::Sys.setgid(Etc.getgrnam(self.gid).gid) if self.gid
        ::Process::Sys.setuid(Etc.getpwnam(self.uid).uid) if self.uid
        Dir.chdir "/"
        $0 = command
        STDIN.reopen "/dev/null"
        STDOUT.reopen "/dev/null", "a"
        STDERR.reopen STDOUT
        exec command
      end
      puts pid.to_s
    end
    
    ::Process.waitpid(opid, 0)
    w.close
    pid = r.gets.chomp
    
    if @tracking_pid or (@pid_file.nil? and WRITES_PID.include?(action))
      File.open(default_pid_file, 'w') do |f|
        f.write pid
      end
      
      @tracking_pid = true
      @pid_file = default_pid_file
    end
    
  elsif command.kind_of?(Proc)
    # lambda command
    command.call
  else
    raise NotImplementedError
  end
end

#default_pid_fileObject



101
102
103
# File 'lib/god/process.rb', line 101

def default_pid_file
  File.join(God.pid_file_directory, "#{self.name}.pid")
end

#pid_fileObject



24
25
26
27
28
29
30
# File 'lib/god/process.rb', line 24

def pid_file
  if @pid_file.nil?
    @tracking_pid = true
    @pid_file = default_pid_file
  end
  @pid_file
end

#pid_file=(value) ⇒ Object

DON’T USE THIS INTERNALLY. Use the instance variable. – Kev No really, trust me. Use the instance variable.



19
20
21
22
# File 'lib/god/process.rb', line 19

def pid_file=(value)
  @tracking_pid = false
  @pid_file = value
end

#restart!Object



40
41
42
# File 'lib/god/process.rb', line 40

def restart!
  call_action(:restart)
end

#start!Object



32
33
34
# File 'lib/god/process.rb', line 32

def start!
  call_action(:start)
end

#stop!Object



36
37
38
# File 'lib/god/process.rb', line 36

def stop!
  call_action(:stop)
end