Class: Freyr::Command

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/freyr/command.rb

Constant Summary collapse

ROOT_PIDS =
'/var/run/freyr'
FREYR_PIDS =
ENV['USER'] == 'root' ? ROOT_PIDS : File.expand_path('.freyr', '~')

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, command = nil, args = {}) ⇒ Command

Returns a new instance of Command.



18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/freyr/command.rb', line 18

def initialize(name, command=nil, args = {})
  if name.is_a?(Service)
    @service = name
    @name = service.name
    @command = service.start_command
    @env = service.env
  else
    @name = name
    @command = command
    
    @env = args[:env]
  end
end

Instance Attribute Details

#commandObject (readonly)

Returns the value of attribute command.



16
17
18
# File 'lib/freyr/command.rb', line 16

def command
  @command
end

#nameObject (readonly)

Returns the value of attribute name.



16
17
18
# File 'lib/freyr/command.rb', line 16

def name
  @name
end

#serviceObject (readonly)

Returns the value of attribute service.



16
17
18
# File 'lib/freyr/command.rb', line 16

def service
  @service
end

Class Method Details

.add_service_method(*methods) ⇒ Object



266
267
268
269
270
271
272
# File 'lib/freyr/command.rb', line 266

def add_service_method *methods
  methods.each do |meth|
    define_method(meth) do |*args|
      @service.__send__(meth,*args) if @service
    end
  end
end

Instance Method Details

#admin?Boolean

Returns:

  • (Boolean)


204
205
206
# File 'lib/freyr/command.rb', line 204

def admin?
  sudo
end

#alive?Boolean

Returns:

  • (Boolean)


51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/freyr/command.rb', line 51

def alive?
  return unless pid
  Process.getpgid(pid)
  true
rescue Errno::ESRCH
  retried = false unless defined?(retried)
  
  if !retried && @pid = pid_from_procname
    save
    retried = true
    retry
  end
  
  if pid(true)
    File.delete(pid_file) unless admin? && !is_root?
  end
  
  false
end

#delete_if_deadObject



71
72
73
# File 'lib/freyr/command.rb', line 71

def delete_if_dead
  !alive?
end

#file_dirObject



36
37
38
# File 'lib/freyr/command.rb', line 36

def file_dir
  admin? ? ROOT_PIDS : FREYR_PIDS
end

#kill!(sig = nil) ⇒ Object



179
180
181
182
183
184
185
186
187
188
# File 'lib/freyr/command.rb', line 179

def kill!(sig=nil)
  require_admin
  sig ||= stop_sig || 'KILL'
  
  Freyr.logger.debug("sending signal to process") {"Signal: #{sig}, PID: #{pid}"}
  
  if pid(true)
    Process.kill(sig, pid)
  end
end

#pid(force = false) ⇒ Object



46
47
48
49
# File 'lib/freyr/command.rb', line 46

def pid(force = false)
  @pid = nil if force
  @pid ||= read_pid
end

#pid_fileObject



32
33
34
# File 'lib/freyr/command.rb', line 32

def pid_file
  File.join(file_dir,"#{@name}.pid")
end

#pid_from_procnameObject



164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/freyr/command.rb', line 164

def pid_from_procname
  return unless proc_match
  
  pids = `ps -eo pid,command`.split("\n").inject({}) do |r, pid|
    if m = pid.match(/^\s*(\d+)\s(.+)$/)
      r[m[2]] = m[1].to_i
    end
    r
  end
  
  if procline = pids.keys.find {|p| p.match(proc_match)}
    pids[procline]
  end
end

#read_pidObject



40
41
42
43
44
# File 'lib/freyr/command.rb', line 40

def read_pid
  return unless File.exist?(pid_file)
  p = File.open(pid_file).read
  p ? p.to_i : nil
end

#restart!Object



190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/freyr/command.rb', line 190

def restart!
  require_admin
  
  if restart
    chdir
    system(restart)
    update_pid
  elsif restart_sig
    kill!(restart_sig)
  else
    run!
  end
end

#run!Object



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
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
154
155
# File 'lib/freyr/command.rb', line 87

def run!
  return unless command
  kill! if alive?
  
  require_admin
  
  total_time = Time.now
  
  pid = spawn(command)
  
  Freyr.logger.debug("attempting to run command") {command.inspect}
  
  @pid = pid
  
  Process.detach(@pid)
  
  if proc_match
    puts "Waiting for pid from match of #{proc_match.inspect}"
    
    start = Time.now
    until (pid = pid_from_procname) || (Time.now-start) > 40
      print '.'; STDOUT.flush
      sleep(0.2)
    end
    
    raise "\nCouldnt find pid after 40 seconds" unless pid
    
    puts '*'
    
    @pid = pid
  end
  
  puts "PID of new #{name} process is #{@pid}"
  save
  
  if ping
    pinger = Pinger.new(self)
    
    puts '',"Waiting for response from #{pinger.url}"
    
    # Move this pinger code somewhere else
    start = Time.now
    begin
      print '.'; STDOUT.flush
      pinger.ping
      sleep(0.6)
    end until pinger.server_probably_launched? || (Time.now-start) > 40 || !alive?
    
    if alive?
      
      if pinger.response
        puts '*',"Last response recieved with code #{pinger.response.code}"
      else
        puts 'x',"Couldn't reach #{name} service"
      end
    else
      puts 'x', "Service died durring launch"
    end
  end
  
  if alive?
    puts "Launch took about #{(Time.now-total_time).ceil} seconds"
    
    @pid
  else
    puts "#{name} service wasn't launched correctly. For details see: #{log}"
    delete_if_dead
  end
end

#saveObject



75
76
77
78
79
80
81
82
83
84
85
# File 'lib/freyr/command.rb', line 75

def save
  if File.exist?(pid_file)
    old_pid = read_pid
    begin
      Process.kill('KILL', old_pid) if old_pid && old_pid.to_s != @pid.to_s
    rescue Errno::ESRCH
    end
  end
  
  File.open(pid_file, 'w') {|f| f.write(@pid)}
end

#update_pidObject



157
158
159
160
161
162
# File 'lib/freyr/command.rb', line 157

def update_pid
  if @pid = pid_from_procname
    save
    @pid
  end
end