ruby-on-rails ruby delayed-job monit god

ruby on rails - Cómo controlar el retraso de trabajo con monit



ruby-on-rails delayed-job (13)

Aquí es cómo lo hice funcionar.

  1. Usa la bifurcación collectiveidea de delayed_job además de mantenerla activa, esta versión tiene un buen script/delayed_job daemon que puedes usar con monit. Railscasts tiene un buen episodio sobre esta versión de delayed_job ( versión ASCIICasts ). Este script también tiene otras características agradables, como la capacidad de ejecutar múltiples trabajadores. No cubro eso aquí.
  2. Instala Monit. Instalé desde la fuente porque la versión de Ubuntu es tan ridículamente desactualizada. Seguí estas instrucciones para obtener los scripts estándar init.d que vienen con los paquetes de Ubuntu. También necesitaba configurar con ./configure --sysconfdir=/etc/monit para que el directorio de configuración de Ubuntu estándar fuera recogido.
  3. Escribe un script monit. Esto es lo que se me ocurrió:

    check process delayed_job with pidfile /var/www/app/shared/pids/delayed_job.pid
    start program = "/var/www/app/current/script/delayed_job -e production start"
    stop program = "/var/www/app/current/script/delayed_job -e production stop"

    Guardo esto en mi sistema de control de soucre y apunto monit con include /var/www/app/current/config/monit en el /etc/monit/monitrc .

  4. Configurar Monit. Estas instrucciones están cargadas de anuncios pero, de lo contrario, están bien.
  5. Escribe una tarea para que capistrano pare y comience. monit start delayed_job y monit stop delayed_job es lo que quieres ejecutar. También recargo monit cuando despliegue para recoger cualquier cambio de archivo de configuración.

Problemas con los que me encontré

  1. daemons gem debe instalarse para que se ejecute el script/delayed_job .
  2. Debe pasar el entorno Rails a script/delayed_job con -e production (por ejemplo). Esto está documentado en el archivo README, pero no en la salida de ayuda del script.
  3. Utilizo Ruby Enterprise Edition, así que necesitaba monit para comenzar con esa copia de Ruby. Debido a la forma en que sudo maneja el PATH en Ubuntu, terminé creando enlaces simbólicos entre /usr/bin/ruby y /usr/bin/gem a las versiones de REE.

Al depurar monit, encontré que ayuda a detener la versión init.d y ejecutarla desde la línea de comando th, para que pueda recibir mensajes de error. De lo contrario, es muy difícil descubrir por qué las cosas van mal.

sudo /etc/init.d/monit stop sudo monit start delayed_job

Esperemos que esto ayude a la siguiente persona que quiera controlar el delayed_job con Monit.

¿Hay algún ejemplo en la web de cómo supervisar el retraso de trabajo con Monit ?

Todo lo que puedo encontrar usa a God , pero me niego a usar a Dios, ya que los procesos de larga duración en Ruby generalmente son una mierda. (La publicación más reciente en la lista de correo de Dios: el uso de la memoria de Dios crece constantemente ).

Actualización: retrayed_job ahora viene con una configuración de monit de muestra basada en esta pregunta.


Como no quería ejecutar como root, terminé creando un script de inicio bash que Monit usó para iniciar y detener (PROGNAME sería la ruta absoluta a script / delayyed_job):

start() { echo "Starting $PROGNAME" sudo -u $USER /usr/bin/env HOME=$HOME RAILS_ENV=$RAILS_ENV $PROGNAME start } stop() { echo "Stopping $PROGNAME" sudo -u $USER /usr/bin/env HOME=$HOME RAILS_ENV=$RAILS_ENV $PROGNAME stop }


Descubrí que era más fácil crear un script de inicio para el trabajo retrasado. Está disponible aquí: http://gist.github.com/408929 o debajo:

#! /bin/sh set_path="cd /home/rails/evatool_staging/current" case "$1" in start) echo -n "Starting delayed_job: " su - rails -c "$set_path; RAILS_ENV=staging script/delayed_job start" >> /var/log/delayed_job.log 2>&1 echo "done." ;; stop) echo -n "Stopping sphinx: " su - rails -c "$set_path; RAILS_ENV=staging script/delayed_job stop" >> /var/log/delayed_job.log 2>&1 echo "done." ;; *) N=/etc/init.d/delayed_job_staging echo "Usage: $N {start|stop}" >&2 exit 1 ;; esac exit 0

Luego, asegúrese de que monit esté configurado para iniciar / reiniciar la aplicación, de modo que en su archivo monitrc:

check process delayed_job with pidfile "/path_to_my_rails_app/shared/pids/delayed_job.pid" start program = "/etc/init.d/delayed_job start" stop program = "/etc/init.d/delayed_job stop"

y eso funciona genial!


Encontré una buena manera de iniciar el trabajo retrasado con cron en el arranque. Estoy usando whenever que controle cron.

Mi schedule.rb:

# custom job type to control delayed_job job_type :delayed_job, ''cd :path;RAILS_ENV=:environment script/delayed_job ":task"'' # delayed job start on boot every :reboot do delayed_job "start" end

Nota: Actualicé cada gema a la versión 0.5.0 para poder usar job_type


Gracias por el guion.

Una gotcha, ya que Monit por definición tiene un "camino espartano" de

/bin:/usr/bin:/sbin:/usr/sbin

... y para mí Ruby fue instalado / vinculado en / usr / local / bin, tuve que lidiar durante horas tratando de descubrir por qué monit estaba fallando silenciosamente al intentar reiniciar el trabajo retrasado (incluso con -v para monit verbose mode) .

Al final tuve que hacer esto:

check process delayed_job with pidfile /var/www/app/shared/pids/delayed_job.pid start program = "/usr/bin/env PATH=$PATH:/usr/local/bin /var/www/app/current/script/delayed_job -e production start" stop program = "/usr/bin/env PATH=$PATH:/usr/local/bin /var/www/app/current/script/delayed_job -e production stop"


He dedicado bastante tiempo a este tema. Estaba harto de no tener una buena solución para él, así que escribí el complemento de retraso_trabajo_tracer que aborda específicamente el monitoreo de trabajo retrasado y sus trabajos.

Aquí hay un artículo que he escrito al respecto: http://modernagility.com/articles/5-monitoring-delayed_job-and-its-jobs

Este complemento supervisará el proceso de trabajo retrasado y le enviará un correo electrónico si se produce un retraso en el trabajo o si uno de sus trabajos falla.


Me encontré con un problema donde si el trabajo retrasado muere mientras todavía tiene un trabajo bloqueado, ese trabajo no será liberado. Escribí un script envoltorio sobre el trabajo retrasado que examinará el archivo pid y liberará cualquier trabajo del trabajador muerto.

El guión es para caucho / capistrano

roles / delayedjob / delayed_job_wrapper:

<% @path = ''/etc/monit/monit.d/monit-delayedjob.conf'' %> <% workers = 4 %> <% workers.times do |i| %> <% PIDFILE = "/mnt/custora-#{RUBBER_ENV}/shared/pids/delayed_job.#{i}.pid" %> <%= "check process delayed_job.#{i} with pidfile #{PIDFILE}"%> group delayed_job-<%= RUBBER_ENV %> <%= " start program = /"/bin/bash /mnt/#{rubber_env.app_name}-#{RUBBER_ENV}/current/script/delayed_job_wrapper #{i} start/"" %> <%= " stop program = /"/bin/bash /mnt/#{rubber_env.app_name}-#{RUBBER_ENV}/current/script/delayed_job_wrapper #{i} stop/"" %> <% end %>

roles / retardo de trabajo / delayed_job_wrapper

#!/bin/bash <% @path = "/mnt/#{rubber_env.app_name}-#{RUBBER_ENV}/current/script/delayed_job_wrapper" %> <%= "pid_file=/mnt/#{rubber_env.app_name}-#{RUBBER_ENV}/shared/pids/delayed_job.$1.pid" %> if [ -e $pid_file ]; then pid=`cat $pid_file` if [ $2 == "start" ]; then ps -e | grep ^$pid if [ $? -eq 0 ]; then echo "already running $pid" exit fi rm $pid_file fi locked_by="delayed_job.$1 host:`hostname` pid:$pid" <%=" /usr/bin/mysql -e /"update delayed_jobs set locked_at = null, locked_by = null where locked_by=''$locked_by''/" -u#{rubber_env.db_user} -h#{rubber_instances.for_role(''db'', ''primary'' => true).first.full_name} #{rubber_env.db_name} " %> fi <%= "cd /mnt/#{rubber_env.app_name}-#{RUBBER_ENV}/current" %> . /etc/profile <%= "RAILS_ENV=#{RUBBER_ENV} script/delayed_job -i $1 $2"%>


No sé con Monit, pero he escrito un par de plugins de Munin para monitorear el tamaño de la cola y el tiempo promedio de ejecución de trabajos. Los cambios que realicé en retaryed_job en ese parche también podrían facilitarle la escritura de complementos Monit en caso de que se quede con eso.


Para Rails 3, es posible que necesite configurar HOME env para hacer que la brújula funcione correctamente, y la configuración siguiente funciona para mí:

check process delayed_job with pidfile /home/user/app/shared/pids/delayed_job.pid start program = "/bin/sh -c ''cd /home/user/app/current; HOME=/home/user RAILS_ENV=production script/delayed_job start''" stop program = "/bin/sh -c ''cd /home/user/app/current; HOME=/home/user RAILS_ENV=production script/delayed_job stop''"


Por lo que vale, siempre puedes usar / usr / bin / env con monit para configurar el entorno. Esto es especialmente importante en la versión actual de retardada_trabajo, 1.8.4, donde la opción de entorno (-e) está en desuso.

check process delayed_job with pidfile /var/app/shared/pids/delayed_job.pid start program = "/usr/bin/env RAILS_ENV=production /var/app/current/script/delayed_job start" stop program = "/usr/bin/env RAILS_ENV=production /var/app/current/script/delayed_job stop"

En algunos casos, es posible que también deba establecer la RUTA con env.


Si su monit se está ejecutando como root y desea ejecutar demoed_job como mi_usuario , haga esto:

/etc/init.d/delayed_job :

#!/bin/sh # chmod 755 /etc/init.d/delayed_job # chown root:root /etc/init.d/delayed_job case "$1" in start|stop|restart) DJ_CMD=$1 ;; *) echo "Usage: $0 {start|stop|restart}" exit esac su -c "cd /var/www/my_app/current && /usr/bin/env bin/delayed_job $DJ_CMD" - my_user

/var/www/my_app/shared/monit/delayed_job.monitrc :

check process delayed_job with pidfile /var/www/my_app/shared/tmp/pids/delayed_job.pid start program = "/etc/init.d/delayed_job start" stop program = "/etc/init.d/delayed_job stop" if 5 restarts within 5 cycles then timeout

/ etc / monit / monitrc :

# add at bottom include /var/www/my_app/shared/monit/*


Tuve que combinar las soluciones en esta página con otra script hecha por toby para que funcione con Monit y comenzar con el usuario correcto.

Así que mi retrayed_job.monitrc se ve así:

check process delayed_job with pidfile /var/app/shared/pids/delayed_job.pid start program = "/bin/su -c ''/usr/bin/env RAILS_ENV=production /var/app/current/script/delayed_job start'' - rails" stop program = "/bin/su -c ''/usr/bin/env RAILS_ENV=production /var/app/current/script/delayed_job stop'' - rails"


para ver qué está pasando, ejecute monit en el modo detallado de primer plano: sudo monit -Iv

utilizando rvm instalado en el usuario "www1" y el grupo "www1".

en el archivo /etc/monit/monitrc :

#delayed_job check process delayed_job with pidfile /home/www1/your_app/current/tmp/pids/delayed_job.pid start program "/bin/bash -c ''PATH=$PATH:/home/www1/.rvm/bin;source /home/www1/.rvm/scripts/rvm;cd /home/www1/your_app/current;RAILS_ENV=production bundle exec script/delayed_job start''" as uid www1 and gid www1 stop program "/bin/bash -c ''PATH=$PATH:/home/www1/.rvm/bin;source /home/www1/.rvm/scripts/rvm;cd /home/www1/your_app/current;RAILS_ENV=production bundle exec script/delayed_job stop''" as uid www1 and gid www1 if totalmem is greater than 200 MB for 2 cycles then alert