# Диагностика сервера (`server:diagnose`) Панель помечает прокси-узел/LB-узел **не в сети** исключительно из-за устаревшего сердцебиения (`enabled` + `status = 1` + недавнее `last_check_ago`), которое никогда не сообщает вам, почему узел перестал сообщать. Команда `server:diagnose` отвечает на этот вопрос. ```bash /home/xc_vm/console.php server:diagnose [server_id] ``` Это команда **доступен только для чтения**: она выполняет только проверки ping/curl/`fsockopen`, `SELECT` запросы и `sudo -n iptables -nL`. Он никогда ничего не перезапускает и не перенастраивает. Реализовано с помощью `src/Cli/Commands/ServerDiagnoseCommand.php`. Команда поставляется в сборках **оба** MAIN и LB — локальный режим - вот и весь смысл ее размещения на узле. --- ## Два режима Режим автоматически выбирается из того, в котором выполняется команда (`server_id` в `config.ini` → `is_main` в таблице `servers`).: ### Режим A — дистанционный датчик от ОСНОВНОГО ```bash sudo /home/xc_vm/console.php server:diagnose ``` Проверяет целевой узел снаружи и считывает его состояние на панели управления: |Проверять|О чем это вам говорит| | --- | --- | |Включено / Статус / Сердцебиение|Как панель в данный момент видит узел (`status = 4` означает сбой установки/подготовки)| |Пинг по протоколу ICMP|Жив ли вообще носитель| |TCP к `http_broadcast_port`|Доступен ли nginx, или порт удален| |HTTP `GET /api`|Действительно ли PHP отвечает за nginx| |Смещение часов|`time_offset` против панели (перекос > 30 с может привести к переключению узла в режим онлайн/оффлайн)| |Очередь сигналов|Неиспользованные строки в `signals` для этого узла (задержка > 120 секунд = цикл обратного вызова узла застрял)| Комбинации датчиков соответствуют причинам: - **Порт ICMP + не закрыт** — узел выключен, разделен сетью или полностью защищен брандмауэром. - **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 (программа записи сердцебиений) не запущен или он не может выполнить запись в базу данных панели. Запустите локальный режим на узле. ### Режим B — локальная самодиагностика НА узле ```bash sudo /home/xc_vm/console.php server:diagnose ``` Запустите это **на самом безмолвном узле 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`). |Код выхода|Значение| | --- | --- | | `0` |Очевидная причина не обнаружена (или цель сама по себе является ОСНОВНОЙ — диагностировать нечего).| | `1` |Ошибка использования: отсутствует/неизвестно `server_id`| | `2` |Была найдена и напечатана одна или несколько вероятных причин| Пример (локальный режим, самоблокирующийся основной): ```text Self-diagnosis on node #3 — LB-Frankfurt (type 1) ---------------------------------------------------------------- [OK] Enabled yes [OK] Status 1 (online) [WARN] Heartbeat last check-in 641s ago (limit 180s) [OK] DB → main reachable (this query ran) [OK] Ping main reply (203.0.113.10) [WARN] Main :8080 closed/timeout [WARN] Main in iptables DROP present (+flood marker) [OK] Service xc_vm active [OK] nginx :8080 listening [OK] watchdog daemon running [OK] cron:servers in xc_vm crontab [OK] Clock offset 2s vs panel ---------------------------------------------------------------- Probable cause(s): 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`. ``` --- ## Краткий справочник — Распространенные причины |Симптом|Вероятная причина|Чинить| | --- | --- | --- | |Звенит, порт сброшен|iptables узла заблокировал основной IP-адрес|`sudo iptables -D INPUT -s -j DROP` + удалить маркер `block_` (команда выводит точную строку)| |Ни пинга, ни порта|Отключен хост / сетевой раздел / внешний брандмауэр|Проверьте консоль хостинга, маршруты, брандмауэр провайдера| |Порт открыт, `/api` отключен|сбой в работе php-fpm|Перезапустите службу `xc_vm` на узле| |`/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 на главном| |Статус = 4|Произошла ошибка установки/обеспечения|Повторный запуск `server:install` из основного| --- ## Связанные файлы |Файл|Роль| | --- | --- | | `src/Cli/Commands/ServerDiagnoseCommand.php` |Диагностическая команда (в обоих режимах)| | `src/Cli/Commands/WatchdogCommand.php` |Демон watchdog — записывает сердцебиение (`last_check_ago`)| | `src/Cli/CronJobs/ServersCronJob.php` |Хрон няни — перезапускает мертвого watchdog| | `src/Cli/CronJobs/RootSignalsCronJob.php` |Применяет блокировки iptables (источник ложных срабатываний)| | `src/Domain/Server/ServerRepository.php` |`servers` доступ к таблице| Смотрите также: [Инструменты интерфейса командной строки](../guides/cli-tools.md), [Обновление сервера](../administration/server-update.md).