supervisor: supervisord и supervisorctl
Менеджер процессов supervisor — секция [program:…], автоперезапуск, логи и команды supervisorctl
Supervisor держит запущенными долгоживущие программы: веб-приложения, воркеры очередей, ботов. Демон supervisord запускает программы, описанные в конфигурации, перезапускает упавшие и собирает их вывод в логи. supervisorctl — пульт управления: показать статус, остановить, запустить, перечитать конфигурацию. Supervisor часто используют там, где нет systemd, — например, в контейнерах. Пакет supervisor написан на Python.
Синтаксис
supervisord [-c файл] [-n] # запустить демон; -n — не уходить в фон
supervisorctl [-c файл] команда [имя…] # одна команда
supervisorctl # интерактивная консоль: supervisor> status
Где лежат файлы (Ubuntu)
| Путь | Что это |
|---|---|
/etc/supervisor/supervisord.conf | главная конфигурация; подключает conf.d/*.conf |
/etc/supervisor/conf.d/имя.conf | конфигурации программ — по файлу на программу |
/var/log/supervisor/supervisord.log | лог самого демона: старты, падения, перезапуски |
/var/log/supervisor/ | логи программ по умолчанию (имя-stdout---supervisor-XXXX.log) |
/var/run/supervisor.sock | сокет, через который supervisorctl говорит с демоном |
Секция [program:имя]
| Ключ | Что задаёт | По умолчанию |
|---|---|---|
command | команда запуска; программа должна работать на переднем плане | обязателен |
directory | рабочий каталог перед запуском | не меняется |
user | от какого пользователя запускать (демон должен работать от root) | пользователь демона |
environment | переменные: KEY="value",KEY2="value2" | — |
autostart | запускать при старте supervisord | true |
autorestart | перезапускать после выхода: true, false, unexpected (только при коде не из exitcodes) | unexpected |
exitcodes | «ожидаемые» коды выхода для autorestart=unexpected | 0 |
startsecs | сколько секунд программа должна проработать, чтобы старт считался успешным | 1 |
startretries | сколько раз пытаться запустить, прежде чем сдаться (FATAL) | 3 |
stopsignal | сигнал для остановки: TERM, INT, QUIT, HUP, KILL, USR1, USR2 | TERM |
stopwaitsecs | сколько ждать после stopsignal, прежде чем послать SIGKILL | 10 |
stopasgroup / killasgroup | слать сигнал всей группе процессов — чтобы не остались потомки | false |
stdout_logfile / stderr_logfile | куда писать вывод; AUTO — в /var/log/supervisor/, NONE — никуда | AUTO |
redirect_stderr | писать stderr в тот же лог, что stdout | false |
stdout_logfile_maxbytes / _backups | размер лога до ротации и число старых копий | 50MB / 10 |
numprocs | сколько копий запустить; нужен process_name с %(process_num) | 1 |
process_name | имя процесса, например %(program_name)s_%(process_num)02d | %(program_name)s |
priority | порядок запуска и остановки: меньше — раньше стартует | 999 |
Несколько программ объединяют в [group:имя] с ключом programs=a,b — тогда ими управляют как имя:*.
Команды supervisorctl
| Команда | Что делает |
|---|---|
status [имя…] | состояние программ: имя, статус, PID, время работы |
start имя / stop имя | запустить / остановить; all — все, группа:* — всю группу |
restart имя | остановить и запустить; конфигурацию не перечитывает |
reread | перечитать конфигурацию и показать, что изменилось (available, changed, disappeared), ничего не применяя |
update [группа] | применить изменения: запустить новые программы, перезапустить изменённые, убрать удалённые |
tail [-f] [-N] имя [stdout|stderr] | показать конец лога программы; -f — следить, -1600 — последние 1600 байт |
maintail [-f] | конец лога самого supervisord |
pid [имя] | PID программы; без имени — PID демона |
signal СИГНАЛ имя | послать сигнал программе: signal HUP web — например, перечитать конфиг |
avail | все программы из конфигурации и в каком они состоянии |
add / remove имя | добавить / убрать одну группу после reread |
clear имя | очистить лог программы |
fg имя | подключиться к программе на переднем плане (выход — Ctrl-C) |
reload | перезапустить сам supervisord — с перезапуском всех программ |
shutdown | остановить supervisord и все программы |
help [команда] | справка |
Состояния в status
| Состояние | Что значит |
|---|---|
RUNNING | работает (прожила дольше startsecs) |
STARTING | запускается, ещё не прошло startsecs |
STOPPED | остановлена вручную или не запускалась (autostart=false) |
STOPPING | останавливается |
BACKOFF | упала при старте, supervisor пробует снова |
EXITED | завершилась после успешного старта и не перезапускается |
FATAL | не удалось запустить за startretries попыток — смотри логи |
UNKNOWN | ошибка в самом supervisor |
supervisorctl status возвращает код 3, если хотя бы одна программа не в состоянии RUNNING, и 4, если не удаётся связаться с демоном.
Примеры
# описать программу
cat > /etc/supervisor/conf.d/web.conf <<'EOF'
[program:web]
command=python3 -m http.server 8000
directory=/tmp
user=nobody
autostart=true
autorestart=true
environment=APP_ENV="prod"
stdout_logfile=/var/log/web.out.log
redirect_stderr=true
EOF
# запустить демон (там, где он не стартует как служба)
supervisord -c /etc/supervisor/supervisord.conf
# применить новую или изменённую конфигурацию
supervisorctl reread
supervisorctl update
# состояние всех программ и одной
supervisorctl status
supervisorctl status web
# перезапуск и просмотр лога
supervisorctl restart web
supervisorctl tail -2000 web
supervisorctl tail -f web stderr
# несколько воркеров одной программы
cat > /etc/supervisor/conf.d/worker.conf <<'EOF'
[program:worker]
command=sleep 1000
numprocs=2
process_name=%(program_name)s_%(process_num)02d
EOF
supervisorctl reread && supervisorctl update
supervisorctl stop 'worker:*'
# почему программа в FATAL
supervisorctl tail web stderr
supervisorctl maintail | tail -20
Подводные камни
restartне видит правок конфигурации. После изменения.confнужныsupervisorctl rereadиsupervisorctl update—updateсам перезапустит изменённую программу.- Программа должна работать на переднем плане. Если
commandуходит в фон (демонизируется, какnginxбезdaemon off;), supervisor видит мгновенный выход, перезапускает её снова и снова, а в итоге ставитFATAL. Ищи у программы опцию «не уходить в фон» (-f,--foreground,daemon off;). FATALсExited too quickly— программа завершилась раньшеstartsecs. Причина обычно в логах программы (tail имя stderr): опечатка в пути, нет прав, не задана переменная окружения.supervisorctlбез демона не работает. Ошибкаunix:///var/run/supervisor.sock no such fileзначит, чтоsupervisordне запущен или слушает другой сокет.environmentне раскрывает$VARкак оболочка. Значения с запятыми и спецсимволами бери в кавычки; переменные окружения демона подставляются через%(ENV_ИМЯ)s.tail -N— это байты, а не строки.supervisorctl tail -100 webпокажет последние 100 байт.- Остановка убивает только главный процесс. Если
command— скрипт-обёртка, его потомки могут остаться жить. Используйexecв обёртке илиstopasgroup=trueиkillasgroup=true. - Состояние группы указывается со звёздочкой:
stop 'worker:*'. Звёздочку бери в кавычки, иначе оболочка может раскрыть её как шаблон файлов.