2 ноября 2012 г. FreeBSD Python Мониторинг Supervisor

FreeBSD. Установка и настройка supervisor

supervisor

Supervisor - это система по управлению процессами в операционной системе. К примеру, у вас есть программы, которые надо перезапускать по определенным правилам, и чтобы для них не писать подсистему для управления (rc-скрипты, систему мониторинга и перезапуска), можно воспользоваться supervisor.

Он запускает процессы как свои подпроцессы, поэтому он имеет над ними полный контроль и знает их точное состояние.

supervisorctl предоставляет системный- и веб-интерфейсы для мониторинга и управления процессами. Вы можете предоставить пользователям доступ на определенные программы, а они в свою очередь смогут видеть состояние этих программ и совершать действия над ними (start, stop, restart). Также имеется XML-RPC интерфейс, которым вы можете пользоваться для написания своих расширений и приложений, которым нужен доступ к supervisord.

Вы можете группировать ваши программы и совершать над ними общие действия (например, перезапуск всех программ). Также есть возможность указывать приоритет для каждой программы, тем самым организуя порядок перезапуска.

Эта замечательная утилита написана на Python, работает на Linux, Mac OS X, Solaris и FreeBSD.
В статье речь идёт о версии 3.0b1

Установка

Для установки достаточно выполнить:

pip install supervisor

Во FreeBSD есть порт sysutils/py-supervisor, но supervisor там более старый чем в PyPI. Если вы всё равно будете использовать порт, то не надо выполнять команду echo_supervisord_conf, так как порт сам скопирует supervisord.conf куда надо.

В порте также есть скрипт инициализации sysutils/py-supervisor/files/supervisord.in. Он менее функциональный, чем мой форк (который я вскоре постараюсь добавить в сам порт), поэтому сразу рекомендую использовать его:
mkdir /var/run/supervisor
fetch -o /usr/local/etc/rc.d/supervisord https://raw.github.com/gist/3809678/supervisord
chmod +x /usr/local/etc/rc.d/supervisord

Наличие скрипта инициализации позволит вам автоматически запускать supervisor в момент запуска операционной системы. Добавьте в /etc/rc.conf:
# Обязательно:
supervisord_enable="YES"
# По желанию:
supervisord_conffile="/usr/local/etc/supervisord.conf" # путь до конфигурационного файла
supervisord_pidfile="/var/run/supervisor/supervisord.pid" # путь до pid-файла
supervisord_user="supervisor"
supervisord_group="supervisor"
supervisord_logdir="/var/log/supervisord"  # скрипт создаст каталог для логов, если его нет

Настройка

Для начала нам надо сгенерировать конфигурационный файл и установить правильные пути до служебных файлов:

mkdir /var/run/supervisor
echo_supervisord_conf | sed -r \
-e "s#/tmp/supervisord.log#/var/log/supervisord.log#" \
-e "s#/tmp/supervisor(d*)\.(.*)#/var/run/supervisor/supervisor\1.\2#" \
> /usr/local/etc/supervisord.conf

Далее открываем в редакторе сгенерированный нами конфиг /usr/local/etc/supervisord.conf и редактируем секцию unix_http_server:

[unix_http_server]
; Путь до сокета
file=/var/run/supervisor/supervisor.sock
; Установите нужные права для файла сокета, иначе другие пользователи ОС не смогут использовать supervisor
chmod=0770
; Аналогично предыдущему, например "supervisor:supervisor"
chown=<uid>:<gid>
; Авторизация в supervisord укажите имя пользователя
username=<username>
; Авторизация в supervisordl: укажите пароль
password=<password>
Если вы указали пользователя и группу supervisor:supervisor в unix_http_server.chown, то стоит добавить их в систему:
pw groupadd supervisor
pw useradd supervisor -G supervisor

Если вы хотите работать с supervisorctl через другого пользователя, то тогда стоит добавить этого пользователя в группу supervisor, например так:
pw usermod <username> -G wheel,supervisor
так как мы разрешили группе иметь доступ к сокету, смотрите unix_http_server.chmod

Если не хотите вводить логин и пароль при входе в supervisorctl, то сразу укажите их в секции supervisorctl:

[supervisorctl]
; Путь до сокета
serverurl=unix:///var/run/supervisor/supervisor.sock
; Имя пользователя из unix_http_server.username
username=<username>
; Пароль из unix_http_server.password
password=<password>

Теперь добавьте инструкции для подключения дополнительных конфигурационных файлов в самый конец файла /usr/local/etc/supervisord.conf:

[include]
; Маска для подключаемых конфигурационных файлов
files = /usr/local/etc/supervisor/*.conf

Пример настройки программы

Создайте файл /usr/local/etc/supervisor/<project>.conf, в котором будут содержаться секции для программ вашего проекта.

И для примера создадим одну секцию с программой <project>_uwsgi, в которой будут находиться инструкции для вашего uWSGI:

[program:<project>_uwsgi]
; Имя программы в supervisor, например будет выводится в supervisorctl
process_name=%(program_name)s
; Вы можете указать сколько таких процессов надо запустить, по умолчанию 1
numprocs=1
; Путь до проекта (chdir)
directory=/<project>
; Команда для запуска программы
command=/<project>/venv/bin/uwsgi /<project>/uwsgi/production.ini
; Из под какого пользователя запускать программу
user=<username>
; При загрузке самого supervisor запускать программу
autostart=true
; Если программа аварийно завершилась, то перезапускать её
autorestart=true
; Перенаправляет пришедший STDERR в ответ supervisor'у в STDOUT (эквивалент /the/program 2>&1)
redirect_stderr=true
; Таймаут в секундах, после которого supervisor пошлет SIGKILL процессу,
; которому до этого посылал SIGCHLD
stopwaitsecs=60
; Какой сигнал посылать для остановки программы
stopsignal=INT
; Путь до error-лога
stderr_logfile=/var/log/<project>/wsgi_err.log
; Путь до output-лога
stdout_logfile=/var/log/<project>/wsgi_out.log
; Максимальный размер файла output-лога, после чего будет "rotate"
stdout_logfile_maxbytes=100MB
; Количество файлов output-лога
stdout_logfile_backups=30
; Размер буфера для output-лога
stdout_capture_maxbytes=1MB

Дополнительные опции этой секции смотрите тут. Примеры секций можно посмотреть тут и тут.

Для того чтобы не писать полные пути до python/pip/uwsgi можно установить переменную окружения:
[program:adw0rd_uwsgi]
environment=PATH="/path/to/project/venv/bin"
directory=/path/to/project
command=uwsgi uwsgi/production.ini
...

Все дело в том, что source venv/bin/activate устанавливает в $PATH абсолютный путь до venv/bin, а мы сами меняем $PATH. Об этом написано тут.

Взято отсюда http://stackoverflow.com/questions/6532486/supervising-virutalenv-django-app-via-supervisor

Использование

Для запуска демона supervisord выполните:

/usr/local/etc/rc.d/supervisord start

Теперь запустите в консоли команду supervisorctl и вы увидите следующее:

supervisor> status
<project>_uwsgi                   RUNNING    pid 54020, uptime 0:01:11

где <project>_uwsgi - имя вашей программы, a RUNNING - текущее состояние вашей программы.

Либо можно вызывать supervisorctl так:

supervisorctl status <project>_uwsgi
supervisorctl restart <project>_uwsgi


Бывают следующие состояния процесса программы:

  • STOPPED - процесс остановлен в обычно порядке, т.е. не аварийно;
  • STARTING - процесс запускается;
  • RUNNING - процесс запущен/работает;
  • BACKOFF - процесс запускался, но так и не запустился (такие процессы supervisor перезапускает. Если не получилось через некоторое время запустить процесс, то статус программы устанавливается в FATAL. Почитайте об опции startretries на этой странице);
  • STOPPING - процесс останавливается;
  • EXITED - процесс завершился (будет автоматически запущен, если установлено autorestart=true);
  • FATAL - процесс не смог запуститься (скорее всего есть ошибки в конфигурационном файле программы);
  • UNKNOWN - неизвестное состояние процесса ("supervisord programming error").

Возможные переходы состояний процесса:

Subprocess State Transition Graph

Далее введите help и вы увидите список доступных команд:

supervisor> help

default commands (type help ):
=====================================
add    clear  fg        open  quit    remove  restart   start   stop  update 
avail  exit   maintail  pid   reload  reread  shutdown  status  tail  version


Составил небольшую табличку со всеми командами:

availВывести все доступные программы
add <name>Активация значений в секции программы или группы
remove <name>Деактивация программы или группы
updateПеречитать файл конфигураций и выполнить add/remove, если необходимо. Например, если мы добавили в конфигурационный файл новую секцию с программой, то после update для неё будет вызван add, а если мы удалим секцию, то remove
status [<name>]Вывести текущее состояние всех процессов либо конкретного процесса, передав его имя
pid [<name>]
[all]
Вывести pid демона supervisord. Если ввести <name>, то выведется pid указаной программы. Если ввести pid all, то выведется список pid'ов для каждого процесса по одному на каждую строчку
start [<name>]
[<gname:*>] [all]
Введите <name>, чтобы запустить процесс или группу по имени. Введите all, чтобы запустить все процессы
stop [<name>]
[<gname:*>] [all]
Введите <name>, чтобы остановить процесс. Введите <gname:*>, чтобы остановить все процессы в группе. Введите all, чтобы остановить все процессы
restart [<name>]
[<gname:*>] [all]
Введите <name>, чтобы перезагрузить процесс или группу по имени. Введите all, чтобы перезагрузить все процессы
fg <name>Подключиться к процессу. После нажатия на Ctrl+c вы вернетесь в supervisorctl
open <url>Присоединиться к удаленному supervisord (формат записи для UNIX-сокета: unix:///socket/path)
shutdownОстановить supervisord
reloadПерезагрузить supervisord
rereadПеречитать файл конфигураций (чтобы не перезагружать сам supervisord)
tail [-f]
[-<num>] <name>
[stdout|stderr]
Вывести логи указанного процесса, для выхода из режима нажать Ctrl+c. Если укажете флаг -f, то tail будет следить за логом и выводить вновь появившиеся данные (в общем, работает по аналогии с консольным вызовом tail -f). Если, например, введете tail -100 , то выведется 100 байт log-файла указанного процесса. По умолчанию выводится stdout
maintail [-f]
[-<num>]
Вывести данные из главного log-файла supervisor'a, для выхода нажать Ctrl+c. Если укажите флаг -f, то maintail будет следить за логом и выводить вновь появившиеся данные (в общем, работает по аналогии с консольным вызовом tail -f). Если, например, введете -100, то выведется 100 байт log-файла
clear [<name>]
[all]
Очистить log-файлы для опеределенных программ (либо для всех программ, если указать all)
versionВывести версию supervisord
exit, quitВыйти из supervisorctl

События в supervisor

В supervisor также есть механизм событий, с помощью которого вы можете ловить события и оповещать о них кого-либо. Пример:

[eventlistener:memmon]
command=memmon -a 200MB -m bob@example.com
events=TICK_60

Более подробно читать тут.

Сторонние приложения и плагины к supervisor

На офицальной странице PLUGINS.rst можно найти интересные плагины, а также внешние приложения, которые интегрированны с supervisor.

Вот некоторые из них:

  • Для мониторинга и контроллирования процессов, например, используемой памяти, можно использовать superlance.
  • С автоподстановкой названий и параллельным запуском команд процессов вам поможет supervisor-wildcards.
  • Для интеграции с Nginx вам может пригодиться ngx_supervisord.
  • Если вы пользуетесь Nagios, то вам может понадобиться Supervisord-Nagios-Plugin.
  • Если вы используете Django, то вам будет удобно установить приложение django-supervisor, которое позволяет вам получать информацию и управлять процессами в supervisor.
  • Если вы используете Fabric, то вам будет интересно попробовать fabtools/supervisor.py.

Комментарии

В Debian можно так установить:

sudo apt-get install supervisor
sudo pip install --upgrade supervisor
sudo ln -s /usr/local/bin/supervisord /usr/bin/supervisord
sudo ln -s /usr/local/etc/supervisord.conf /etc/supervisord.conf

Тогда у вас будет init-скрипт и свежий supervisor.

Если не запускается supervisord, а в логах ничего нет, то запустите его с опцией --nodaemon

Тогда он вас будет информировать в stdout.

unix:///var/run/supervisor/supervisor.sock no such file

Это кто сказал? ls?

ls /var/run/supervisor/supervisor.sock

В кофниге /usr/local/etc/supervisord.conf у вас unix_http_server.file равен "/var/run/supervisor/supervisor.sock"?

на моюильном плохо рендерится табличка
"Составил небольшую табличку со всеми командами:"

ttys, исправил, спасибо!

Как настроить при перезапуске одной программы в группе (авторестарт), принудительный рестарт всей группы? Например запущены несколько сервисов, использующие совместные ресурсы, сервак падает, нужно автоматически перезапустить сервер и перезапустить клиенты тоже.

@hamster1979, вы читали http://www.supervisord.org/events.html ?

А Вы?

@hamster1979 я то да, даже использовал, там все ответы есть на ваш вопрос. Покажите примеры использования, что конкретно у вас не получилось?

Оставьте свой комментарий

Markdown