How to control nginx passenger with monit

I have several rail applications deployed by nginx passenger. I want these applications to be monitored using monit. How can I control these applications using monit? Should I also keep an eye on nginx?

+4
source share
3 answers

This is how I solved it. First, I added in application.rb:

# Monit support if defined?(PhusionPassenger) require 'pidfile_manager' PhusionPassenger.on_event(:starting_worker_process) do |forked| if forked # We're in smart spawning mode. PidfileManager.write_pid_file else # We're in conservative spawning mode. We don't need to do anything. end end PhusionPassenger.on_event(:stopping_worker_process) do PidfileManager.remove_pid_file end end 

and then I implemented PidfileManager:

 module PidfileManager extend self BASENAME = '/var/tmp/rack.*.pid' def write_pid_file pid = Process.pid count = 1 pidfile = nil go_over_pid_files do |file, saved_pid| file_id = file[/(\d+)/,1].to_i # Increase counter only if we met the same file id count += 1 if file_id == count # We're already there return if saved_pid == pid # Check if the process is alive res = begin Process.kill(0, saved_pid) rescue Errno::ESRCH nil end # It dead, reuse unless res pidfile = file break end end pidfile ||= BASENAME.sub('*', count.to_s) File.open(pidfile, 'w') {|f| f.write(pid.to_s)} end def remove_pid_file pid = Process.pid go_over_pid_files do |file, saved_pid| if pid == saved_pid File.unlink(file) break end end end private def go_over_pid_files Dir[BASENAME].each do |file| saved_pid = File.read(file).to_i yield file, saved_pid end end end 

And then you just tell monit to control each instance using /var/tmp/rack.X.pid as the pidfile.

+3
source

Not sure it's too late to post this, but this is how I use monit (5.14) to stop passenger rail applications that consume too much memory:

monitor:

 check program ourapp_live with path "/usr/local/bin/check_passenger_mem_usage ourapp 500" as "ourappuser" if status != 0 then alert if status != 0 then restart start program = "/bin/touch /var/www/vhosts/ourapp/railsapp/current/tmp/restart.txt" stop program = "/bin/true" 

Script shell label (check_passenger_mem_usage):

 #!/bin/bash # # USER=$1 TRIGGER=$2 if [ -z $USER ] || [ -z $TRIGGER ] then echo "missing args" echo "usage:" echo " check_passenger_mem_usage username alert_threshold" echo echo "(alert_threshold is in mb)" echo exit 1 fi MAX=`/usr/local/rvm/gems/ruby-1.8.7-p357/wrappers/passenger-memory-stats | grep $USER | awk '{print $2}' | sort -n | tail -1|cut -d. -f1` if [ "$MAX" -gt $TRIGGER ] then echo echo "${USER}: We got a runaway! Gobbling ${MAX} mb" echo exit 1 else echo echo "Max is ${MAX}" exit 0 fi 

This is probably not the best solution, since it restarts the entire rails application, but at least it prevents the use of rails that consume huge amounts of memory if the application works a bit intensively with memory over and over again.

+2
source

If you want to keep them working and restart them, if there is an error, you can better watch supervisord . Instead of polling to check if the process is running, supervisord actually starts the process itself. The daemons that it launches need to start the front panel in order for it to work, but it is very efficient and will bring services much faster than monit (monit usually checks every minute, while the supervisor will see the process complete and restart it instantly).

We use the supervisor in production, in which all our daemons are involved (nginx, beanstalkd, memcached, various python services, etc.), and then use monit to monitor the supervisor as an additional backup.

0
source