Skip to content

diagnose: на хосте без контейнера remnanode сенсор даёт ложный ✘ и ломает --json (docker inspect печатает пустую строку перед ошибкой) #27

Closed

Description

@jestivald

Что происходит

На хосте, где контейнера remnanode нет (панель-бокс, CDN-origin с иначе названным контейнером), na-diagnose v4.0.1:

  1. в текстовом режиме вместо ветки info "remnanode: контейнера нет" уходит в ложный критический пункт — итог ✔ 34 ▲ 0 ✘ 1 и совет «Запусти ⚡ оптимизатор и 🛡 защиту», хотя оба модуля только что применены:

    ✘  remnanode: статус '
    absent' (не running) — node-агент лежит
    
  2. в --json отдаёт невалидный JSON — сырой перевод строки внутри строкового значения:

    $ na-diagnose --json | python3 -m json.tool
    json.decoder.JSONDecodeError: Invalid control character at: line 1 column 789 (char 788)
    

    т.е. ломается контракт «стабильный na-diagnose --json для мониторинга/панели» ровно на тех хостах, где мониторинг по нему и хочется собирать. На ноде с живым контейнером (remnanode_status":"running") JSON валиден.

Корень

scripts/diagnose.sh:641 (текст) и :100 (json):

RN_ST="$(docker inspect -f '{{.State.Status}}' remnanode 2>/dev/null || echo absent)"

docker inspect -f по несуществующему объекту (Docker 29.7.2, build a7dcaa6) печатает в stdout пустую строку и только потом падает с rc=1:

$ docker inspect -f '{{.State.Status}}' remnanode 2>/dev/null | od -c
0000000  \n
$ v="$(docker inspect -f '{{.State.Status}}' remnanode 2>/dev/null || echo absent)"; printf '%q\n' "$v"
$'\nabsent'

Подстановка $(…) срезает только ХВОСТОВЫЕ переводы строки, поэтому значение становится "\nabsent": [[ "$RN_ST" == absent ]] ложно → bad; гард в json-ветке [[ -n "$rnst" ]] || rnst=absent тоже не срабатывает (строка непустая), и \n уезжает в printf '"remnanode_status":"%s"' как есть. rnrc с тем же шаблоном спасает регэксп ^[0-9]+$, поэтому симптом только у статуса.

Наблюдалось

2026-09-01, раскатка v4.0.1 на 8 хостов: панель-бокс (Debian 12, Docker 29.7.2) — оба симптома стабильно; 7 нод с контейнером — чисто. В v4.0 то же (пункт был в списке «косметика» с 31.08, но невалидный --json косметикой уже не назвать).

Предлагаемый фикс

Не смешивать stdout и код возврата, нормализовать пробелы и пустоту считать отсутствием — в обеих ветках:

RN_ST="$(docker inspect -f '{{.State.Status}}' remnanode 2>/dev/null | tr -d '[:space:]')"
[[ -n "$RN_ST" ]] || RN_ST=absent

Плюс в json-эмиттере пропускать строковые значения через экранирование (\n, ", \), чтобы любое будущее «сырое» значение не могло сломать документ. Тест: tests/ — стаб docker, который на inspect печатает \n и возвращает 1; ждём info-ветку и валидный JSON.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions