Как отслеживать delayed_job с помощью monit
Есть ли в сети примеры того, как контролировать delayed_job с Monit?
Все, что я могу найти, использует Бога, но я отказываюсь использовать Бога, так как длительные процессы в Ruby, как правило, отстой. (Самый последний пост в списке рассылки Бога? Использование памяти Бога неуклонно растет.)
Обновление: delayed_job теперь поставляется с примером конфигурации monit, основанной на этом вопросе.
13 ответов
Вот как я получил это работает.
- Кроме того, в дополнение к активной поддержке, вы можете использовать в коллективной форме форк delayed_job.
script/delayed_job
демон, который вы можете использовать с monit. У Railscasts есть хороший эпизод об этой версииdelayed_job
( Версия ASCIICasts). Этот скрипт также имеет некоторые другие приятные функции, такие как возможность запуска нескольких рабочих. Я не рассматриваю это здесь. - Установить монит. Я установил из источника, потому что версия Ubuntu так смешно устарела. Я следовал этим инструкциям, чтобы получить стандартные скрипты init.d, которые поставляются с пакетами Ubuntu. Мне также нужно было настроить с
./configure --sysconfdir=/etc/monit
поэтому был выбран стандартный каталог конфигурации Ubuntu. Напишите скрипт monit. Вот что я придумал:
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"
Я сохраняю это в моей системе управления soucre и указываю на это с помощью
include /var/www/app/current/config/monit
в/etc/monit/monitrc
файл.- Настроить монит. Эти инструкции заполнены рекламой, но в остальном все в порядке.
- Напишите задачу для Capistrano, чтобы остановить и начать.
monit start delayed_job
а такжеmonit stop delayed_job
это то, что вы хотите запустить. Я также перезагружаю monit при развертывании, чтобы получить любые изменения в файле конфигурации.
Проблемы, с которыми я столкнулся:
daemons
камень должен быть установлен дляscript/delayed_job
бежать.- Вы должны передать среду Rails
script/delayed_job
с-e production
(например). Это задокументировано в файле README, но не в выводе справки скрипта. - Я использую Ruby Enterprise Edition, поэтому мне нужно было запустить monit для запуска этой копии Ruby. Из-за способа, которым sudo обрабатывает PATH в Ubuntu, я закончил тем, что создал символическую ссылку
/usr/bin/ruby
а также/usr/bin/gem
к версиям REE.
При отладке monit я обнаружил, что это помогает остановить версию init.d и запустить ее из командной строки th, чтобы вы могли получать сообщения об ошибках. В противном случае очень трудно понять, почему все идет не так.
sudo /etc/init.d/monit stop
sudo monit start delayed_job
Надеюсь, это поможет следующему человеку, который хочет контролировать delayed_job
с монит.
Что бы это ни стоило, вы всегда можете использовать /usr/bin/env с monit для настройки среды. Это особенно важно в текущей версии delayed_job, 1.8.4, где опция среды (-e) устарела.
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"
В некоторых случаях вам также может понадобиться установить PATH с помощью env.
Я нашел хороший способ запустить delayed_job с помощью cron при загрузке. Я использую всякий раз, чтобы контролировать cron.
Мой график.rb:
# пользовательский тип задания для управления delayed_job тип задания:delayed_job, 'cd: путь;RAILS_ENV=: сценарий среды /delayed_job ": задача"' # отложенное начало работы при загрузке каждые: перезагрузка делать delayed_job "начало" конец
Примечание: я обновлял gem до версии 0.5.0, чтобы можно было использовать job_type
Я обнаружил, что было проще создать сценарий инициализации для отложенной работы. Это доступно здесь: http://gist.github.com/408929 или ниже:
#! / Бен / ш set_path="cd /home/rails/evatool_staging/current" дело "1 доллар" в Начните) echo -n "Запуск delayed_job: " su - rails -c "$set_path; RAILS_ENV= сценарий постановки / отложенное начало работы" >> /var/log/delayed_job.log 2>&1 эхо "сделано".;; стоп) echo -n "Остановка сфинкса:" su - rails -c "$ set_path; RAILS_ENV = сценарий постановки / остановка отложенного задания" >> /var/log/delayed_job.log 2>&1 эхо "сделано".;; *) N=/ и т.д. / init.d / delayed_job_staging echo "Использование: $N {start|stop}" >&2 выход 1;; ESAC выход 0
Затем убедитесь, что monit настроен на запуск / перезапуск приложения в вашем файле monitrc:
проверить процесс delayed_job с помощью pidfile "/path_to_my_rails_app/shared/pids/delayed_job.pid" start program = "/etc/init.d/delayed_job start" остановить программу = "/etc/init.d/delayed_job stop"
и это прекрасно работает!
Если ваш монитор работает от имени пользователя root и вы хотите запустить delayed_job от имени my_user, сделайте следующее:
/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/*
Мне пришлось объединить решения на этой странице с другим скриптом, созданным toby, чтобы он работал с monit и начинался с подходящего пользователя.
Так что мой delayed_job.monitrc выглядит так:
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"
Спасибо за сценарий.
Одна ошибка - поскольку у monit по определению есть "спартанский путь"
/bin:/usr/bin:/sbin:/usr/sbin
... и для меня ruby был установлен / подключен в /usr/local/bin, мне пришлось часами разбираться, пытаясь выяснить, почему monit молча терпел неудачу при попытке перезапустить delayed_job (даже с -v для режима monit verbose),
В итоге мне пришлось сделать это:
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"
С Monit я не знаю, но я написал пару плагинов Munin для мониторинга размера очереди и среднего времени выполнения задания. Изменения, которые я внес в delayed_job в этом патче, могут также облегчить вам написание плагинов Monit на случай, если вы будете придерживаться этого.
Для Rails 3 вам может понадобиться установить HOME env, чтобы компас работал правильно, и нижеприведенный конфиг работает для меня:
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'"
Так как я не хотел запускаться от имени пользователя root, я закончил тем, что создал сценарий bash init, который monit использовался для запуска и остановки (PROGNAME был бы абсолютным путем к script/delayed_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
}
Я потратил довольно много времени на эту тему. Я был сыт по горло отсутствием хорошего решения для него, поэтому я написал плагин delayed_job_tracer, который специально посвящен мониторингу delayed_job и его задачам.
Вот статья, которую я написал об этом: http://modernagility.com/articles/5-monitoring-delayed_job-and-its-jobs
Этот плагин будет следить за процессом отложенной работы и отправлять вам электронное письмо в случае сбоя delayed_job или сбоя одной из его работ.
Чтобы увидеть, что происходит, запустите monit в подробном режиме переднего плана: sudo monit -Iv
с помощью rvm
устанавливается под пользователем "www1" и группой "www1".
в файле /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
Я столкнулся с проблемой, когда, если отложенное задание умирает, пока оно еще заблокировано, оно не будет освобождено. Я написал скрипт-оболочку для отложенной работы, которая будет смотреть на файл pid и освобождать любые задания от мертвого работника.
Скрипт для резины / капистрано
Роли /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 %>
Роли / delayedjob / 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"%>