Панель помечает прокси-узел/LB-узел **не в сети** исключительно из-за устаревшего сердцебиения (`enabled` + `status = 1` + недавнее `last_check_ago`), которое никогда не сообщает вам, почему узел перестал сообщать. Команда `server:diagnose` отвечает на этот вопрос.
Это команда **доступен только для чтения**: она выполняет только проверки ping/curl/`fsockopen`, `SELECT` запросы и `sudo -n iptables -nL`. Он никогда ничего не перезапускает и не перенастраивает.
Реализовано с помощью `src/Cli/Commands/ServerDiagnoseCommand.php`. Команда поставляется в сборках **оба** MAIN и LB — локальный режим - вот и весь смысл ее размещения на узле.
- **ICMP replies but the port is dropped** — the classic: the node's own iptables blocked the main's IP (RootSignals flood/block false-positive), or nginx/the service is down. Run the local mode on the node for the exact cause.
- **Порт открыт, но `/api` молчит** — nginx запущено, PHP - нет: проверьте php-fpm на узле.
- **`/api` отвечает, но сердцебиение затихает** — демон узла watchdog (программа записи сердцебиений) не запущен или он не может выполнить запись в базу данных панели. Запустите локальный режим на узле.
Запустите это **на самом безмолвном узле LB/proxy** — причины обычно находятся там. Аргумент не требуется; узел идентифицирует себя по `config.ini`. Проверки:
1.**Мой собственный ряд панелей** — включено/статус/сердцебиение в том виде, в каком их видит основной пользователь.
2.**Могу ли я добраться до ГЛАВНОГО** — Подключение к базе данных (неявно подтвержденное), ICMP и TCP к широковещательному порту главного сервера.
3.**Отключил ли я главный брандмауэр?** — сканирует цепочку `iptables INPUT` этого узла на наличие `DROP` IP-адреса главного узла, а также файла-маркера блокировки потока. Это классическая причина "узел отключился без причины": защита от наводнений автоматически отключает общедоступные IP-адреса, и обратные вызовы главного сервера перестают поступать.
4.**Услуга / nginx** — `systemctl is-active xc_vm` и локальная проверка TCP на собственном широковещательном порту узла.
5.**Демон-сторожевой пес** — фактический регистратор сердцебиений: демон `watchdog` обновляет `last_check_ago` каждые несколько секунд. Когда его MySQL подключение к главному серверу прерывается, он **ожидает возврата базы данных** (повторяет попытку каждые 5 секунд) и немедленно возобновляет сердцебиение. Вместо этого были запущены более старые сборки, что приводило к **все узлы переходят в автономный режим в один и тот же момент** при любом MySQL перезапуске / сбое в главном меню, пока `cron:servers` не восстановило их.
6.**Няня крон** — три дополнительных проверки, потому что мертвый watchdog остается мертвым только тогда, когда цепочка няни разорвана:
- присутствует ли `cron:servers` в **`xc_vm` кронтаб пользователя** (если отсутствует, восстановите с помощью `rm -f /home/xc_vm/tmp/crontab` и перезапустите службу);
- активна ли система **служба cron** (нет cron → crontab никогда не запускается);
- является предыдущим `cron:servers` экземпляром **висел на своем замке cron** — зависший экземпляр блокирует каждый последующий запуск на срок до 30 минут (`acquireCronLock` истекший тайм-аут), что в точности соответствует тому, как один сбой в работе базы данных удерживает узел в автономном режиме в течение получаса. Команда выводит удерживающий PID и команду завершения.
7.**Перекос часов** — `time_offset` против панели.
> **Примечание:** для проверки iptables требуется sudo без пароля (`sudo -n`). Без него проверка выдает сообщение о `cannot check (need sudo iptables)` вместо сбоя — запустите команду как `root` для получения полной картины.
При каждой проверке выводится одна выровненная строка `[OK]`/`[WARN]`, за которой следует пронумерованная сводка **Вероятная причина (причины)** с указанием точной команды исправления там, где она существует (например, строка разблокировки `iptables -D INPUT ... -j DROP`).
1. Heartbeat is stale (641s > 180s): the node stopped reporting — the checks below narrow down why.
2. This node has DROPPED the main's IP 203.0.113.10 in its own iptables (flood/block false-positive). Unblock: `sudo iptables -D INPUT -s 203.0.113.10 -j DROP && sudo rm -f /home/xc_vm/tmp/flood/block_203.0.113.10`.
|`/api` отлично, сердцебиение замедлилось|Сторожевой демон мертв (завершает работу при потере соединения с базой данных)|`sudo -u xc_vm console.php watchdog` на узле; проверьте разрешения базы данных (`tools mysql` на главном сервере)|
| **All nodes drop at the same moment** |Перезапуск MySQL /сбой на главном сервере приводит к одновременному сбою watchdog на каждом узле (фатально для сборок до исправления; текущие сборки переждут это).|Проверьте журнал ошибок main MySQL во время сброса; обновите узлы, чтобы watchdog пережил перебои в работе|
|Закрылки узлов онлайн/оффлайн|Перекос часов > 30 с (или повторяющиеся сигналы MySQL)|Синхронизируйте протокол NTP на узле; проверьте стабильность MySQL на главном|