bluepill 0.0.63 → 0.0.64

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -87,6 +87,19 @@ To watch the modification time of a file, e.g. a log file to ensure the process
87
87
  end
88
88
  ```
89
89
 
90
+ To restart process if it's running too long:
91
+
92
+ ```ruby
93
+ Bluepill.application("app_name") do |app|
94
+ app.process("process_name") do |process|
95
+ process.start_command = "/usr/bin/some_start_command"
96
+ process.pid_file = "/tmp/some_pid_file.pid"
97
+
98
+ process.checks :running_time, :every => 10.minutes, :below => 24.hours
99
+ end
100
+ end
101
+ ```
102
+
90
103
 
91
104
 
92
105
  We can tell bluepill to give a process some grace time to start/stop/restart before resuming monitoring:
@@ -12,7 +12,7 @@ RbConfig = Config unless Object.const_defined?(:RbConfig)
12
12
  # Default options
13
13
  options = {
14
14
  :log_file => "/var/log/bluepill.log",
15
- :base_dir => "/var/run/bluepill",
15
+ :base_dir => ENV['BLUEPILL_BASE_DIR'] || (::Process.euid != 0 ? File.join(ENV['HOME'], '.bluepill') : "/var/run/bluepill"),
16
16
  :privileged => true,
17
17
  :timeout => 10,
18
18
  :attempts => 1
@@ -111,6 +111,7 @@ if options[:command] == "load"
111
111
  ruby = File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'])
112
112
  load_path = File.expand_path("#{File.dirname(__FILE__)}/../lib")
113
113
  file_path = File.expand_path(file)
114
+ ENV['BLUEPILL_BASE_DIR'] = options[:base_dir]
114
115
 
115
116
  exec(ruby, "-I#{load_path}", '-rbluepill', file_path)
116
117
 
@@ -15,7 +15,7 @@ Gem::Specification.new do |s|
15
15
  s.description = %q{Bluepill keeps your daemons up while taking up as little resources as possible. After all you probably want the resources of your server to be used by whatever daemons you are running rather than the thing that's supposed to make sure they are brought back up, should they die or misbehave.}
16
16
 
17
17
  s.add_dependency 'daemons', ['~> 1.1.4']
18
- s.add_dependency 'state_machine', '~> 1.1.0'
18
+ s.add_dependency 'state_machine', '~> 1.1'
19
19
  s.add_dependency 'activesupport', '>= 3.0.0'
20
20
  s.add_dependency 'i18n', '>= 0.5.0'
21
21
 
@@ -16,7 +16,9 @@ module Bluepill
16
16
 
17
17
  @foreground = options[:foreground]
18
18
  self.log_file = options[:log_file]
19
- self.base_dir = ProcessJournal.base_dir = options[:base_dir] || '/var/run/bluepill'
19
+ self.base_dir = ProcessJournal.base_dir = options[:base_dir] ||
20
+ ENV['BLUEPILL_BASE_DIR'] ||
21
+ (::Process.euid != 0 ? File.join(ENV['HOME'], '.bluepill') : "/var/run/bluepill")
20
22
  self.pid_file = File.join(self.base_dir, 'pids', self.name + ".pid")
21
23
  self.pids_dir = File.join(self.base_dir, 'pids', self.name)
22
24
  self.kill_timeout = options[:kill_timeout] || 10
@@ -281,7 +281,7 @@ module Bluepill
281
281
  logger.warning "Executing start command: #{start_command}"
282
282
  if self.daemonize?
283
283
  daemon_id = System.daemonize(start_command, self.system_command_options)
284
- if daemon_id > 0
284
+ if daemon_id
285
285
  ProcessJournal.append_pid_to_journal(name, daemon_id)
286
286
  children.each {|child|
287
287
  ProcessJournal.append_pid_to_journal(name, child.actual_id)
@@ -0,0 +1,18 @@
1
+ # -*- encoding: utf-8 -*-
2
+ module Bluepill
3
+ module ProcessConditions
4
+ class RunningTime < ProcessCondition
5
+ def initialize(options = {})
6
+ @below = options[:below]
7
+ end
8
+
9
+ def run(pid, include_children)
10
+ System.running_time(pid)
11
+ end
12
+
13
+ def check(value)
14
+ value < @below
15
+ end
16
+ end
17
+ end
18
+ end
@@ -14,7 +14,8 @@ module Bluepill
14
14
  :pid => 0,
15
15
  :ppid => 1,
16
16
  :pcpu => 2,
17
- :rss => 3
17
+ :rss => 3,
18
+ :etime => 4
18
19
  }
19
20
 
20
21
  def pid_alive?(pid)
@@ -48,6 +49,12 @@ module Bluepill
48
49
  mem_used
49
50
  end
50
51
 
52
+ def running_time(pid)
53
+ ps = ps_axu
54
+ return unless ps[pid]
55
+ parse_elapsed_time(ps[pid][IDX_MAP[:etime]])
56
+ end
57
+
51
58
  def get_children(parent_pid)
52
59
  child_pids = Array.new
53
60
  ps_axu.each_pair do |pid, chunks|
@@ -189,7 +196,7 @@ module Bluepill
189
196
  wr.write Marshal.dump(result)
190
197
  wr.close
191
198
 
192
- exit
199
+ ::Process.exit!
193
200
  end
194
201
  end
195
202
 
@@ -205,7 +212,7 @@ module Bluepill
205
212
  # TODO: need a mutex here
206
213
  store[:ps_axu] ||= begin
207
214
  # BSD style ps invocation
208
- lines = `ps axo pid,ppid,pcpu,rss`.split("\n")
215
+ lines = `ps axo pid,ppid,pcpu,rss,etime`.split("\n")
209
216
 
210
217
  lines.inject(Hash.new) do |mem, line|
211
218
  chunks = line.split(/\s+/)
@@ -217,6 +224,19 @@ module Bluepill
217
224
  end
218
225
  end
219
226
 
227
+ def parse_elapsed_time(str)
228
+ # [[dd-]hh:]mm:ss
229
+ if str =~ /(?:(?:(\d+)-)?(\d\d):)?(\d\d):(\d\d)/
230
+ days = ($1 || 0).to_i
231
+ hours = ($2 || 0).to_i
232
+ mins = $3.to_i
233
+ secs = $4.to_i
234
+ ((days*24 + hours)*60 + mins)*60 + secs
235
+ else
236
+ 0
237
+ end
238
+ end
239
+
220
240
  # be sure to call this from a fork otherwise it will modify the attributes
221
241
  # of the bluepill daemon
222
242
  def drop_privileges(uid, gid, supplementary_groups)
@@ -1,4 +1,4 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  module Bluepill
3
- VERSION = "0.0.63".freeze
3
+ VERSION = "0.0.64".freeze
4
4
  end
@@ -17,7 +17,7 @@ RbConfig = Config unless Object.const_defined?(:RbConfig)
17
17
  # Default options
18
18
  options = {
19
19
  :log_file => "/var/log/bluepill.log",
20
- :base_dir => "/var/run/bluepill",
20
+ :base_dir => ENV['BLUEPILL_BASE_DIR'] || (::Process.euid != 0 ? File.join(ENV['HOME'], '.bluepill') : "/var/run/bluepill"),
21
21
  :privileged => true,
22
22
  :timeout => 10,
23
23
  :attempts => 1
@@ -114,8 +114,9 @@ if options[:command] == "load"
114
114
  # Restart the ruby interpreter for the config file so that anything loaded here
115
115
  # does not stay in memory for the daemon
116
116
  ruby = File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'])
117
- load_path = File.expand_path("#{File.dirname(__FILE__)}/../lib")
117
+ load_path = File.expand_path("#{File.dirname(__FILE__)}/lib")
118
118
  file_path = File.expand_path(file)
119
+ ENV['BLUEPILL_BASE_DIR'] = options[:base_dir]
119
120
 
120
121
  exec(ruby, "-I#{load_path}", '-rbluepill', file_path)
121
122
 
@@ -0,0 +1,31 @@
1
+ describe Bluepill::Application do
2
+ describe "#initialize" do
3
+ let(:options){ {} }
4
+ subject {described_class.new('test', options)}
5
+ before(:each) {described_class.any_instance.should_receive(:setup_pids_dir)}
6
+
7
+ context "when euid is not root" do
8
+ before(:each) {::Process.stub(:euid).and_return(1)}
9
+ its(:base_dir){ should eq(File.join(ENV['HOME'], '.bluepill')) }
10
+ end
11
+ context "when euid is root" do
12
+ before(:each) {::Process.stub(:euid).and_return(0)}
13
+ its(:base_dir) { should eq('/var/run/bluepill') }
14
+ end
15
+
16
+ context "when option base_dir is specified" do
17
+ let(:options) { {:base_dir=>'/var/bluepill'} }
18
+ its(:base_dir) { should eq(options[:base_dir]) }
19
+ end
20
+
21
+ context "when environment BLUEPILL_BASE_DIR is specified" do
22
+ before(:each) {ENV['BLUEPILL_BASE_DIR'] = '/bluepill'}
23
+ its(:base_dir) { should eq(ENV['BLUEPILL_BASE_DIR']) }
24
+
25
+ context "and option base_dir is specified" do
26
+ let(:options) { {:base_dir=>'/var/bluepill'} }
27
+ its(:base_dir) { should eq(options[:base_dir]) }
28
+ end
29
+ end
30
+ end
31
+ end
@@ -33,4 +33,13 @@ describe Bluepill::System do
33
33
  Bluepill::System.store.should be_empty
34
34
  end
35
35
  end
36
+
37
+ describe :parse_etime do
38
+ it "should parse etime format" do
39
+ Bluepill::System.parse_elapsed_time("400-00:04:01").should be_equal(34560241)
40
+ Bluepill::System.parse_elapsed_time("02:04:02").should be_equal(7442)
41
+ Bluepill::System.parse_elapsed_time("20:03").should be_equal(1203)
42
+ Bluepill::System.parse_elapsed_time("invalid").should be_equal(0)
43
+ end
44
+ end
36
45
  end
@@ -12,4 +12,10 @@ require 'rspec/core'
12
12
 
13
13
  $LOAD_PATH.unshift(File.expand_path('../lib', File.dirname(__FILE__)))
14
14
 
15
+ module Process
16
+ def self.euid
17
+ raise "Process.euid should be stubbed"
18
+ end
19
+ end
20
+
15
21
  require 'bluepill'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bluepill
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.63
4
+ version: 0.0.64
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2013-04-21 00:00:00.000000000 Z
14
+ date: 2013-05-29 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: daemons
@@ -36,7 +36,7 @@ dependencies:
36
36
  requirements:
37
37
  - - ~>
38
38
  - !ruby/object:Gem::Version
39
- version: 1.1.0
39
+ version: '1.1'
40
40
  type: :runtime
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
@@ -44,7 +44,7 @@ dependencies:
44
44
  requirements:
45
45
  - - ~>
46
46
  - !ruby/object:Gem::Version
47
- version: 1.1.0
47
+ version: '1.1'
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: activesupport
50
50
  requirement: !ruby/object:Gem::Requirement
@@ -207,6 +207,7 @@ files:
207
207
  - lib/bluepill/process_conditions/http.rb
208
208
  - lib/bluepill/process_conditions/mem_usage.rb
209
209
  - lib/bluepill/process_conditions/process_condition.rb
210
+ - lib/bluepill/process_conditions/running_time.rb
210
211
  - lib/bluepill/process_journal.rb
211
212
  - lib/bluepill/process_statistics.rb
212
213
  - lib/bluepill/socket.rb
@@ -216,6 +217,7 @@ files:
216
217
  - lib/bluepill/util/rotational_array.rb
217
218
  - lib/bluepill/version.rb
218
219
  - local-bluepill
220
+ - spec/lib/bluepill/application_spec.rb
219
221
  - spec/lib/bluepill/logger_spec.rb
220
222
  - spec/lib/bluepill/process_spec.rb
221
223
  - spec/lib/bluepill/process_statistics_spec.rb
@@ -235,7 +237,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
235
237
  version: '0'
236
238
  segments:
237
239
  - 0
238
- hash: 4302574804058768595
240
+ hash: -2865814049117051220
239
241
  required_rubygems_version: !ruby/object:Gem::Requirement
240
242
  none: false
241
243
  requirements:
@@ -244,7 +246,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
244
246
  version: '0'
245
247
  segments:
246
248
  - 0
247
- hash: 4302574804058768595
249
+ hash: -2865814049117051220
248
250
  requirements: []
249
251
  rubyforge_project:
250
252
  rubygems_version: 1.8.24
@@ -252,6 +254,7 @@ signing_key:
252
254
  specification_version: 3
253
255
  summary: A process monitor written in Ruby with stability and minimalism in mind.
254
256
  test_files:
257
+ - spec/lib/bluepill/application_spec.rb
255
258
  - spec/lib/bluepill/logger_spec.rb
256
259
  - spec/lib/bluepill/process_spec.rb
257
260
  - spec/lib/bluepill/process_statistics_spec.rb