Skip to content

Supervisord

Sayapin Alexander edited this page Jan 27, 2016 · 17 revisions

Supervisord - это демон, написанный на Python, который используется для слежением за работой процессов.

Фактически основная задача Supervisord - это запуск, перезапускать и слежение за процессами. А ещё он имеет консоль, в которой доступны основные команды (список процессов, статус, запуск, останов, перезапуск и т.д. ), web-консоль доступную через HTTP, HTTP-API, он умеет перехватывать вывод в STDOUT или STDERR, перенаправлять потоки в файлы, отображать логи в web-интерфейсе и т.д.

Основные достоинства

  • Очень простой файл конфигураций
  • Доступен в репозиториях Debian / Ubuntu и других ОС (ставится через apt-get или pip)
  • Имеет систему плагинов и event-listener'ов - т.е. расширяем
  • Достаточно простой, но мощный
    • Он знает о процессах
    • Знает о pid-файлах
    • Знает о приоритетах и именах процессов
    • Знает о группах, пользователях, umask
    • Умеет запускать группы процессов
    • Имеет настройки по автоматическому запуску, перезапуску, рабочей директории для процессов, переменных окружения, таймаут на запуск, количество попыток перезапуска, кодах завершения и т.д.
    • Умеет запускать от пользователя
    • Умеет rotate-ить файлы логов (потоки STDERR и STDOUT)
  • Достаточно легковесный
  • Умеет работать с потоками ввода/вывода
  • Есть консоль для администратора с основными командами (консоль, кстати, умеет работать с удалёнными машинами)
  • Есть WEB-интерфейс
  • Поддерживает аутентификацию
  • Умеет работать через UNIX SOCKETS
  • Есть XML-RPC-API
  • Версия из репозиториев придерживается debian-way, а это значит, что supervisord можно использовать совместно с установкой DEB-пакетов

Установка

Suervisord есть в стандартных репозиториях debian, соответственно нужно просто выполнить команды

$ sudo apt-get update
$ sudo apt-get install supervisor

все зависимости будут подтянуты автоматически (а это python и т.д.).

проверим, что supervisor запустился

$ ps -uxa | grep supervisor
root       439  0.0  0.1  52436 13128 ?        Ss   19:00   0:00 /usr/bin/python /usr/bin/supervisord -c /etc/supervisor/supervisord.conf

Если не запустился (например, при запуске из-под docker), то просто запустим его

$ sudo /etc/init.d/supervisor start

Ещё он поддерживает вот такие команды:

$ sudo /etc/init.d/supervisor 
Usage: /etc/init.d/supervisord {start|stop|restart|force-reload|status|force-stop}

Файлы конфигурации

Если посмотреть на наименование процесса, то можно увидеть конфигурационный файл, который использует supervisor. Файл конфигурации находится по адресу /etc/supervisor/supervisord.conf

Конфиг очень простой. Важно в конфиге увидеть следующее:

; The [include] section can just contain the "files" setting.  This
; setting can list multiple files (separated by whitespace or
; newlines).  It can also contain wildcards.  The filenames are
; interpreted as relative to this file.  Included files *cannot*
; include files themselves.

[include]
files = /etc/supervisor/conf.d/*.conf

То есть, файлы с расширением *.conf из /etc/supervisor/conf.d/ тоже используются в конфигурации, а это означает что наш конфиг нужно просто положить в директорию, чтобы он "подцепился" после перезапуска. Очень удобно для наведения порядка в конфигах или, например, в случае, если мы создаём deb-пакет с информацией для supervisor.

Пример файла конфигурации

Для начала создадим простой долгоживущий процесс, который будет выводить в STDOUT текущее время.

В моём случае это будет /root/cmd1.sh

#!/bin/bash

while sleep 1; do
    date
done

Теперь создадим файл конфигурации для запуска процесса /etc/supervisor/conf.d/cmd1.conf.

[program:prg1]
command=/root/cmd1.sh

Файл конфигурации очень похож на INI-файл Windows.

  • Секция program описывает программу для старта
  • Секция описывается как [program:<Имя программы>]
  • Имя программы - это значащее для нас имя, так как это имя будет отображаться в списке процессов, участвовать в имени логов и т.д.
  • command= - это команда для запуска

Теперь перезапустим supervisor и посмотрим, что получилось.

$ sudo /etc/init.d/supervisor restart
$ ps -uxa        
...
root      1290  0.0  0.0  17688  2744 ?        S    19:19   0:00 /bin/bash /root/cmd1.sh
root      2066  0.0  0.0   4112   452 ?        S    19:25   0:00 sleep 1
...

Вот процессы, который нас интересуют. Попробуем убить процесс.

$ sudo kill -9 1290
$ ps -uxa 
...
root      2192  0.0  0.0  17664  2616 ?        S    19:26   0:00 /bin/bash /root/cmd1.sh
root      2193  0.0  0.0   4112   480 ?        S    19:26   0:00 sleep 1
...

Как видим процесс перезапустился и об этом свидетельствует новый PID процесса.

Supervisor реагирует на коды завершения, соответственно, логика перезапуска зависит кодов и настроек, если код равен 0, то перезапуск не будет произведён.

Посмотрим на логи, которые пишет supervisor и как он перехватывает потоки приложения. Логи по умолчанию расположены тут: /var/log/supervisor/

/var/log/supervisor/supervisord.log

2015-02-23 19:19:25,910 CRIT Supervisor running as root (no user in config file)
2015-02-23 19:19:25,910 WARN Included extra file "/etc/supervisor/conf.d/cmd1.conf" during parsing
2015-02-23 19:19:25,937 INFO RPC interface 'supervisor' initialized
2015-02-23 19:19:25,937 WARN cElementTree not installed, using slower XML parser for XML-RPC
2015-02-23 19:19:25,937 CRIT Server 'unix_http_server' running without any HTTP authentication checking
2015-02-23 19:19:25,937 INFO daemonizing the supervisord process
2015-02-23 19:19:25,937 INFO supervisord started with pid 1289
2015-02-23 19:19:26,940 INFO spawned: 'prg1' with pid 1290
2015-02-23 19:19:27,941 INFO success: prg1 entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2015-02-23 19:26:52,797 INFO exited: prg1 (terminated by SIGKILL; not expected)
2015-02-23 19:26:53,800 INFO spawned: 'prg1' with pid 2192
2015-02-23 19:26:54,802 INFO success: prg1 entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2015-02-23 19:28:29,507 INFO exited: prg1 (terminated by SIGTERM; not expected)
2015-02-23 19:28:30,509 INFO spawned: 'prg1' with pid 2385
2015-02-23 19:28:31,511 INFO success: prg1 entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2015-02-23 19:29:01,036 INFO exited: prg1 (terminated by SIGTERM; not expected)
2015-02-23 19:29:02,039 INFO spawned: 'prg1' with pid 2452
2015-02-23 19:29:03,040 INFO success: prg1 entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)

Файлы с потоками от приложений расположены там же:

$ sudo ls -lah /var/log/supervisor/prg1-std*
-rw------- 1 root root   0 Feb 23 19:19 /var/log/supervisor/prg1-stderr---supervisor-TA58AK.log
-rw------- 1 root root 23K Feb 23 19:33 /var/log/supervisor/prg1-stdout---supervisor-iKQUvY.log

Мы назвали наше приложение как prg1, соответственно и файлы потоками названы как prg1-stdout... и prg1-stderr....

Можно убедиться, что в файлы содержится вывод приложения:

$ sudo tail /var/log/supervisor/prg1-stdout---supervisor-iKQUvY.log 
Mon Feb 23 19:34:32 UTC 2015
Mon Feb 23 19:34:33 UTC 2015
Mon Feb 23 19:34:34 UTC 2015
Mon Feb 23 19:34:35 UTC 2015
Mon Feb 23 19:34:36 UTC 2015
Mon Feb 23 19:34:37 UTC 2015
Mon Feb 23 19:34:38 UTC 2015
Mon Feb 23 19:34:39 UTC 2015
Mon Feb 23 19:34:40 UTC 2015
Mon Feb 23 19:34:41 UTC 2015

Интерактивная консоль supervisorctl

На самом деле это не просто интерактивная консоль, а панель управления supervisor. С интерактивным и неинтерактивным режимом.

Запустим консоль и посмотрим команды

$ sudo supervisorctl
prg1                             RUNNING    pid 2452, uptime 0:08:57
supervisor> help

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

supervisor> help tail
tail [-f] <name> [stdout|stderr] (default stdout)
Ex:
tail -f <name>		Continuous tail of named process stdout
			Ctrl-C to exit.
tail -100 <name>	last 100 *bytes* of process stdout
tail <name> stderr	last 1600 *bytes* of process stderr

А вот пример использования консоли в неинтерактивном режиме.

$ sudo supervisorctl tail -100 prg1
:18 UTC 2015
Mon Feb 23 19:41:19 UTC 2015
Mon Feb 23 19:41:20 UTC 2015
Mon Feb 23 19:41:21 UTC 2015

Мы получили последние 100 байт из потока STDOUT приложения prg1.

Изменим файл конфигурации и перезапустим приложение из консоли.

[program:prg1]
command=/root/cmd1.sh

[program:prg2]
command=/root/cmd1.sh

Описание процесса:

$ ps -uxa
...
root      2452  0.0  0.0  17720  2692 ?        S    19:29   0:00 /bin/bash /root/cmd1.sh
...
$ sudo supervisorctl 
prg1                             RUNNING    pid 2452, uptime 0:15:33
supervisor> help

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

supervisor> avail
prg1                             in use    auto      999:999
supervisor> help reread
reread 			Reload the daemon's configuration files
supervisor> reread
prg2: available
supervisor> avail
prg1                             in use    auto      999:999
prg2                             avail     auto      999:999

Мы перечитали конфиграцию, воспользовавшись командой reread. В списке доступных программ появилась prg2, а список посмотрели командой avail.

Запустим наше второе приложение:

supervisor> help add
add <name> [...]	Activates any updates in config for process/group
supervisor> add prg2
prg2: added process group
supervisor> avail
prg1                             in use    auto      999:999
prg2                             in use    auto      999:999
supervisor> status
prg1                             RUNNING    pid 2452, uptime 0:18:24
prg2                             RUNNING    pid 4663, uptime 0:00:13
^D
$ ps -uxa 
root      2452  0.0  0.0  17732  2704 ?        S    19:29   0:00 /bin/bash /root/cmd1.sh
root      4663  0.0  0.0  17664  2792 ?        S    19:47   0:00 /bin/bash /root/cmd1.sh

У нас теперь запущено 2 процесса, а первый процесс не изменил своего PID'а, то есть не был перезапущен.

Попробуем остановить процесс.

$ sudo supervisorctl 
prg1                             RUNNING    pid 2452, uptime 0:19:40
prg2                             RUNNING    pid 4663, uptime 0:01:29
supervisor> help stop
stop <name>		Stop a process
stop <gname>:*		Stop all processes in a group
stop <name> <name>	Stop multiple processes or groups
stop all		Stop all processes
supervisor> stop prg1
prg1: stopped
supervisor> status
prg1                             STOPPED    Feb 23 07:49 PM
prg2                             RUNNING    pid 4663, uptime 0:01:55
^D
$ ps -uxa 
root      4663  0.0  0.0  17672  2800 ?        S    19:47   0:00 /bin/bash /root/cmd1.sh

Запуск остановленного процесса осуществляется командой start

supervisor> start prg1
prg1: started
^D

А можно ещё перезапустить процесс, но уже командой restart. :)

HTTP интерфейс

У supervisord есть и web-интерфейс. Чтобы активировать его, добавим следующие строки в /etc/supervisor/supervisord.conf

[inet_http_server]
port=*:9001
username=root
password=root

То есть, добавим web-интерфейс по адресу и порту 0.0.0.0:9001. Данные для авторизации будут root / root.

Перейдём в браузере по адресу: http://127.0.0.1:9001

и увидим такое окно: 1.png Процесс можно остановить, нажав на stop

2.png ...запустить, нажав на start

3.png ... а нажав на имя приложения можно увидеть лог приложения.

4.png ... есть даже возможность видеть лог в реальном времени с обновлением. Для это есть ссылка tail -f

Пример создания deb-пакета с регистрацией приложения

Создадим простой deb-пакет, который будет добавлять конфиг с приложением и запускать приложение в supervisord.

Я буду создавать пакет в /root/. После команд вызова редактора vim располагается содержимое редактируемых файлов для наглядности.

# mkdir package
# cd package
# mkdir -p DEBIAN
# mkdir -p etc/supervisor/conf.d/
# cp /etc/supervisor/conf.d/cmd1.conf etc/supervisor/conf.d/cmd2.conf
# vim etc/supervisor/conf.d/cmd2.conf
[program:prg3]
command=/root/cmd1.sh
# vim DEBIAN/control
Package: tmp
Version: 0.2
Maintainer: Some Person <[email protected]>
Architecture: all
Depends: supervisor
Description: Source simple package
# vim DEBIAN/postinst
#!/bin/bash

supervisorctl reread
supervisorctl add prg3
# cd ..
# chmod +x package/DEBIAN/postinst
# dpkg -b package
dpkg-deb: building package `tmp' in `package.deb'.

А теперь установим пакет, чтобы посмотреть как зарегистрируется и запустится приложение

# dpkg -i package.deb 
Selecting previously unselected package tmp.
(Reading database ... 9616 files and directories currently installed.)
Unpacking tmp (from package.deb) ...
Setting up tmp (0.2) ...
prg3: available
prg3: added process group
# supervisorctl status
prg1                             RUNNING    pid 7475, uptime 0:40:48
prg2                             RUNNING    pid 6590, uptime 0:44:37
prg3                             RUNNING    pid 17254, uptime 0:00:08

Как видим приложение запустилось.

  • TODO:
  • user
  • process_name
  • autorestart
  • autostart
  • priority
  • directory

Ссылки по теме

Clone this wiki locally