Supervisor
Glossary overview

Supervisor

Supervisor — менеджер процесів для Linux. Його задача проста: тримати вказані тобою процеси запущеними і перезапускати їх, якщо вони впали. Supervisor може тримати запущеним будь-що, що має працювати постійно: queue workers, Horizon, Laravel Reverb (WebSockets), Node.js сервер, Go-бінарник, Python-скрипт — що завгодно.

Без Supervisor тобі довелося б або тримати відкритий термінал з queue:work (нереально на проді).

В контексті Laravel — основний юзкейс це queue workers (php artisan queue:work). Без Supervisor worker зупиниться після помилки або перезавантаження сервера, і ніхто не піднімає його знову. Supervisor вирішує цю проблему.

Що ставлять під Supervisor

  • Laravel queue workers (queue:work)
  • Laravel Horizon (php artisan horizon)
  • Laravel Reverb / WebSocket сервер
  • Node.js процеси
  • Будь-який фоновий процес, що має працювати 24/7

Встановлення

Спочатку визначаємо ОС сервера — від цього залежить пакетний менеджер:

cat /etc/os-release

CentOS / AlmaLinux / CloudLinux (типово для WHM/cPanel):

yum install supervisor -y
systemctl enable supervisord
systemctl start supervisord

Ubuntu / Debian:

apt install supervisor -y
systemctl enable supervisor
systemctl start supervisor

Зверни увагу: на CentOS сервіс називається supervisord, на Ubuntu — supervisor.

Конфігурація

Конфіги лежать у /etc/supervisord.d/ (CentOS) або /etc/supervisor/conf.d/ (Ubuntu). Кожен процес — окремий .conf файл (на CentOS розширення .ini).

Базовий конфіг для Laravel queue worker

[program:shop-worker]
process_name=%(program_name)s_%(process_num)02d
command=/usr/local/bin/ea-php84 /home/username/public_html/shop/artisan queue:work redis --sleep=3 --tries=3 --max-time=3600
directory=/home/username/public_html/shop
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=username
numprocs=2
redirect_stderr=true
stdout_logfile=/home/username/public_html/shop/storage/logs/worker.log
stopwaitsecs=3600

Параметри конфігу

ПараметрОпис
[program:shop-worker]Ім’я програми — використовується в командах supervisorctl
process_nameШаблон імені для кожного процесу при numprocs > 1
commandКоманда запуску. Вказуємо повний шлях до PHP та artisan
directoryРобоча директорія (cd перед запуском)
autostart=trueЗапускати при старті Supervisor
autorestart=trueПерезапускати при падінні
stopasgroup=trueЗупиняти разом з дочірніми процесами
killasgroup=trueВбивати разом з дочірніми процесами
userВід якого юзера запускати (cPanel-юзер акаунту)
numprocsКількість паралельних воркерів
redirect_stderr=trueПомилки пишуться в той самий лог
stdout_logfileШлях до лог-файлу
stopwaitsecsСкільки секунд чекати завершення перед kill

Параметри queue:work

ПрапорецьОпис
--sleep=3Скільки секунд спати коли черга порожня
--tries=3Макс. спроб обробки задачі перед failed
--max-time=3600Перезапуск воркера через годину (запобігає витоку пам’яті)
--queue=high,default,lowПріоритет черг (зліва направо)
--timeout=60Макс. час виконання одної задачі

Нюанси WHM/cPanel

PHP-бінарник

cPanel з EasyApache використовує свій шлях до PHP — не /usr/bin/php, а /usr/local/bin/ea-php84 (або інша версія). Перевірити:

# Побачити всі доступні версії PHP на сервері
ls /usr/local/bin/ea-php*

# Або знайти конкретну
which ea-php84

User

В полі user конфігу Supervisor вказуємо cPanel-юзера акаунту (той, під яким лежать файли в /home/username/), а не root чи nobody.

Шляхи

cPanel розміщує сайти в /home/username/public_html/, а не в /var/www/. Якщо Laravel-проект лежить у піддиректорії: /home/username/public_html/shop/.

Термінал

Все виконується через SSH або WHM → Server Configuration → Terminal. WHM Terminal працює від root, тому sudo не потрібен.

Команди supervisorctl

Після створення або зміни конфігу

# Перечитати конфіги (знайде нові/змінені)
supervisorctl reread

# Застосувати зміни (запустити нові, зупинити видалені)
supervisorctl update

Важливо: reread тільки читає конфіги, але не застосовує. Завжди виконуй обидві команди послідовно.

Керування процесами

# Статус всіх процесів
supervisorctl status

# Приклад виводу:
# shop-worker:shop-worker_00   RUNNING   pid 12345, uptime 2:15:30
# shop-worker:shop-worker_01   RUNNING   pid 12346, uptime 2:15:30

# Керування конкретною програмою
supervisorctl start shop-worker:*      # Запустити всі воркери
supervisorctl stop shop-worker:*       # Зупинити всі
supervisorctl restart shop-worker:*    # Перезапустити всі

# Керування конкретним процесом
supervisorctl start shop-worker:shop-worker_00
supervisorctl stop shop-worker:shop-worker_01

# Перезапустити все
supervisorctl restart all

Перегляд логів

# Лог конкретного процесу (останні рядки)
supervisorctl tail shop-worker:shop-worker_00

# В реальному часі
supervisorctl tail -f shop-worker:shop-worker_00

# Або напряму з файлу
tail -f /home/username/public_html/shop/storage/logs/worker.log

Supervisor + Horizon

Horizon — надбудова від Laravel над queue:work. Він сам керує воркерами зсередини (кількість процесів, балансування, автоскейлінг) і дає веб-дашборд на /horizon. Horizon не замінює Supervisor — вони працюють разом.

Без Horizon: Supervisor запускає кілька queue:work процесів, ти сам конфігуруєш кількість та параметри в .conf файлі.

З Horizon: Supervisor запускає один процес — php artisan horizon, а Horizon вже сам піднімає та керує потрібною кількістю воркерів.

[program:horizon]
command=/usr/local/bin/ea-php84 /home/username/public_html/shop/artisan horizon
directory=/home/username/public_html/shop
autostart=true
autorestart=true
user=username
redirect_stderr=true
stdout_logfile=/home/username/public_html/shop/storage/logs/horizon.log
stopwaitsecs=3600

Зверни увагу: numprocs немає — Horizon сам розбереться зі кількістю воркерів. Horizon потребує Redis як драйвер черги.

Після деплою нового коду

Queue workers кешують код при запуску. Після деплою потрібно їх перезапустити, щоб вони підхопили зміни:

# Без Horizon — плавний перезапуск (worker дочекає поточну задачу)
php artisan queue:restart

# З Horizon
php artisan horizon:terminate
# Supervisor автоматично перезапустить Horizon

queue:restart ставить сигнал “зупинись після поточної задачі”. Supervisor бачить що процес зупинився і піднімає новий — вже з оновленим кодом. З Horizon — horizon:terminate робить те саме, після чого Supervisor перезапускає Horizon.

Типові проблеми та дебаг

Worker одразу в FATAL або BACKOFF

# Перевірити лог
supervisorctl tail shop-worker:shop-worker_00

# Типові причини:
# - Невірний шлях до PHP або artisan
# - Немає прав на директорію (user невірний)
# - Redis не запущений (якщо драйвер redis)
# - .env відсутній або невалідний

supervisorctl: command not found

# Supervisor не встановлений
yum install supervisor -y     # CentOS
apt install supervisor -y     # Ubuntu

# Або сервіс не запущений
systemctl start supervisord   # CentOS
systemctl start supervisor    # Ubuntu

Worker працює, але задачі не обробляються

# Перевірити що Redis працює
redis-cli ping
# Має відповісти: PONG

# Перевірити що .env має правильний драйвер
grep QUEUE_CONNECTION /home/username/public_html/shop/.env
# QUEUE_CONNECTION=redis

# Перевірити що конфіг закешований з правильним .env
cd /home/username/public_html/shop
/usr/local/bin/ea-php84 artisan config:cache

Лог-файл росте безконтрольно

Supervisor не ротує логи автоматично. Додай ротацію в конфіг:

stdout_logfile_maxbytes=10MB
stdout_logfile_backups=5

Це обмежить лог до 10 МБ і зберігатиме 5 бекапів.

Повний приклад: від нуля до працюючої черги на WHM

# 1. Встановити Supervisor (WHM Terminal, від root)
yum install supervisor -y
systemctl enable supervisord
systemctl start supervisord

# 2. Перевірити шлях до PHP
ls /usr/local/bin/ea-php*

# 3. Створити конфіг
nano /etc/supervisord.d/shop-worker.ini

# 4. Вставити конфіг (замінити username та шляхи):
# [program:shop-worker]
# process_name=%(program_name)s_%(process_num)02d
# command=/usr/local/bin/ea-php84 /home/username/public_html/shop/artisan queue:work redis --sleep=3 --tries=3 --max-time=3600
# directory=/home/username/public_html/shop
# autostart=true
# autorestart=true
# stopasgroup=true
# killasgroup=true
# user=username
# numprocs=2
# redirect_stderr=true
# stdout_logfile=/home/username/public_html/shop/storage/logs/worker.log
# stdout_logfile_maxbytes=10MB
# stdout_logfile_backups=5
# stopwaitsecs=3600

# 5. Зберегти (Ctrl+O, Ctrl+X) і застосувати
supervisorctl reread
supervisorctl update

# 6. Перевірити
supervisorctl status
# shop-worker:shop-worker_00   RUNNING
# shop-worker:shop-worker_01   RUNNING

Практика

Пдивимось список всіх процесів під Supervisor в WHM.

[root@~]# supervisorctl status
laravel-horizon                  RUNNING   pid 1358128, uptime 3 days, 10:18:23
reverb                           RUNNING   pid 1360176, uptime 3 days, 10:18:07
sprm-worker                      RUNNING   pid 1358130, uptime 3 days, 10:18:23

Три процеси, аптайм 3+ дні — значить стабільно, нічого не падає.

По суті бачимо класичний Laravel-стек: laravel-horizon керує чергами (і сам всередині піднімає воркери), reverb — WebSocket сервер для реалтайм подій, sprm-worker — судячи з назви, окремий queue worker для специфічних задач.

Якщо хочеш подивитися конфіги, вони мають лежати в /etc/supervisord.d/, вот например конфиг filament админки:

[root@ ~]# cat /etc/supervisord.d/sprm-worker.ini
[program:sprm-worker]
command=/opt/cpanel/ea-php83/root/usr/bin/php artisan horizon
directory=/home/****/oparamese.com
autostart=true
autorestart=true
user=****
redirect_stderr=true
stdout_logfile=/home/***/sprm-worker.log

Мы тут для нашего сайта запускаем horizon.