passenger_mon 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/README +26 -0
  2. data/bin/passenger_mon +87 -0
  3. metadata +74 -0
data/README ADDED
@@ -0,0 +1,26 @@
1
+ ## tl;dr ##
2
+
3
+ Simple rails process monitoring for passenger 3.
4
+
5
+ ## Usage ##
6
+
7
+ passenger_mon needs to be run as root to properly get access to Passenger's
8
+ `passenger-memory-stats` output.
9
+
10
+ # Check for out of control processes every 10 seconds
11
+ sudo passenger_mon --interval=10
12
+
13
+
14
+ ## Problem
15
+
16
+ Currently, Passenger 3 (and previous versions) don't generate pidfiles or the
17
+ application processes it spawns. This makes it very difficult to monitor these
18
+ processes with tools like monit and [god](http://github.com/mojombo/god). Further
19
+ compounding this problem is the lack of any sort of per process memory threshold
20
+ for passenger.
21
+
22
+
23
+ ## Contributors
24
+
25
+ * Rick Bradley
26
+ * Alex Sharp
data/bin/passenger_mon ADDED
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'fileutils'
5
+
6
+ options = {}
7
+
8
+ op = OptionParser.new do |opts|
9
+ opts.banner = 'Usage: passenger_mon [options]'
10
+
11
+ opts.on("-i=SECONDS", "--interval=SECONDS", "Poll interval in seconds (default: 10)") do |interval|
12
+ options[:interval] = interval
13
+ end
14
+
15
+ opts.on("-m=MEMORY", "--memory=MB", "Memory threshold in MB (default: 800)") do |mb|
16
+ options[:threshold] = mb
17
+ end
18
+
19
+ opts.on_tail("-h", "--help", "show this message") do
20
+ abort(opts.to_s)
21
+ end
22
+ end.parse!
23
+
24
+ # set option defaults
25
+ options[:interval] ||= 10
26
+ options[:threshold] ||= 800
27
+ options[:threshold] = options[:threshold].to_i
28
+
29
+ process_name = 'passenger_mon'
30
+ pidfile = "/tmp/#{process_name}.pid"
31
+
32
+ # If a pidfile exists when we start up, we need to remove it.
33
+ # This probably means a non-clean shutdown the last time
34
+ # the program was shutdown.
35
+ if File.exist?(pidfile)
36
+ $stdout.puts "Existing pidfile found. Removing..."
37
+ FileUtils.rm(pidfile)
38
+ end
39
+
40
+ # remove the pidfile on shutdown
41
+ at_exit do
42
+ $stdout.puts "Removing pidfile."
43
+ FileUtils.rm(pidfile)
44
+ end
45
+
46
+ # write out the pidfile
47
+ File.open(pidfile, 'w') { |f| f.puts($$) }
48
+
49
+ require 'logger'
50
+ logger = Logger.new("/var/log/passenger_mon.log")
51
+
52
+ Signal.trap('INT') do
53
+ logger.info "Shutting down now..."
54
+ abort("\n")
55
+ end
56
+
57
+ kill_attempts = {}
58
+
59
+ loop do
60
+ logger.info "Checking for naughty processes..."
61
+
62
+ results = `passenger-memory-stats`
63
+ results = results.split("\n").grep(/Rails/)
64
+
65
+ results.each do |res|
66
+ pid, vm_size, vm_size_label, mem_res, *bullshit = res.strip.split(/\s+/)
67
+
68
+ # ultimately, we need to have some logic in here that decides when
69
+ # it's appropriate to do a kill -9. If a process has truly run out of
70
+ # control (say, it's trying to load a massive table into memory at once)
71
+ # then we need to be more aggressive with how we terminate the process.
72
+ if mem_res.to_i >= options[:threshold]
73
+ if kill_attempts.has_key?(pid)
74
+ kill_attempts[pid] += 1
75
+ else
76
+ kill_attempts[pid] = 1
77
+ end
78
+
79
+ logger.info "Killing process #{pid} using #{mem_res.to_i}mb of ram (Threshold=#{options[:threshold]}mb)"
80
+
81
+ # passenger treats the USR1 signal as a graceful shutdown.
82
+ Process.kill("USR1", pid.to_i)
83
+ end
84
+ end
85
+
86
+ sleep options[:interval].to_i
87
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: passenger_mon
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Alex Sharp
14
+ - Rick Bradley
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2011-03-09 00:00:00 -08:00
20
+ default_executable:
21
+ dependencies: []
22
+
23
+ description: Need to control the memory footprint of your passenger processes. You need passenger_mon, bro.
24
+ email:
25
+ - ajsharp@gmail.com
26
+ executables:
27
+ - passenger_mon
28
+ extensions: []
29
+
30
+ extra_rdoc_files:
31
+ - README
32
+ files:
33
+ - README
34
+ - bin/passenger_mon
35
+ has_rdoc: true
36
+ homepage: https://github.com/ajsharp/passenger_mon
37
+ licenses: []
38
+
39
+ post_install_message:
40
+ rdoc_options: []
41
+
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ hash: 57
50
+ segments:
51
+ - 1
52
+ - 8
53
+ - 7
54
+ version: 1.8.7
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ hash: 23
61
+ segments:
62
+ - 1
63
+ - 3
64
+ - 6
65
+ version: 1.3.6
66
+ requirements: []
67
+
68
+ rubyforge_project:
69
+ rubygems_version: 1.3.7
70
+ signing_key:
71
+ specification_version: 3
72
+ summary: Rails process monitoring for passenger 3
73
+ test_files: []
74
+