ActiveScaleинженерная практика

Коды возврата и маркеры завершения

Справочники exit-codesmarkersinstallinstall-ngreference

Коротко. Установка ActiveScale состоит из трёх независимых процессов с тремя разными маркерами: marvin_install пишет /tmp/marvin_initialize.rc и удаляет себя, install-ng пишет /tmp/.unattended_install_finished с кодом внутри, а задачи живут в состоянии SUCCESS/FAILURE/QUEUED. Код возврата 0 не доказывает результат: часть фаз при неверном входе завершается нулём, ничего не меняя.


1. Почему «EXIT=0» ничего не значит

install-ng устроен так, что main() вызывает фазы; каждая фаза при «мягкой» ошибке логирует её и возвращает управление. Процесс всегда заканчивает работу через mark_and_exit(rc): пишет строку кода в маркер и выходит. Функция _error даёт rc=1, штатное завершение — rc=0.

Беда в том, что rc=0 покрывает два разных исхода:

Исход Код Как выглядит дальше
Фаза выполнила работу 0 объекты в модели появились, гейты проходят
Фаза «прошла мимо» (неверный вход, пустая группа политики, лишний флаг) 0 снаружи зелёное, внутри пусто

Классический пример: -AST без группы политики в dssconfig.yml завершается rc=0, колонка создаётся пустой, и только следующий -C падает 500 at least one S3 connection is required. Если смотреть на код первого прогона, всё «хорошо».

Отсюда правило: код возврата — это признак «процесс закончился», а не «работа сделана». Результат подтверждают гейты из статьи о приёмке и проверки ниже.


2. Три маркера установки

2.1 marvin_install (stage 2, initialize)

/usr/bin/marvin_install запускается вручную и сам: - вызывает initialize.py, затем initialize_marvin.py; - разворачивает mongodb, marvinweb, marvintaskmgr; - создаёт /home/marvin/initial_environment.json; - переносит upgrade-архив в /home/marvin; - удаляет себя и пишет /tmp/marvin_initialize.rc.

Признаки завершения (все вместе, а не по одному):

ls -l /usr/bin/marvin_install          # файла нет — скрипт самоудалился
cat /tmp/marvin_initialize.rc          # код возврата initialize
tail -n 20 /opt/ampli/var/log/marvin/deploy.log   # в конце — Done
ls -l /home/marvin/initial_environment.json       # файл создан

Сервис marvin_install.service продукт не регистрирует — это задумка, а не поломка. Если запускать через самодельный юнит, не делайте его Type=forking: сломается таймаут.

2.2 install-ng (stage 3)

Единственный надёжный маркер — файл /tmp/.unattended_install_finished. Внутри — строка кода возврата. Строки DONE_RC в выводе нет, сколько бы её ни искали в логах.

cat /tmp/.unattended_install_finished

Перед каждым повторным прогоном маркер удаляют: rm -f /tmp/.unattended_install_finished. Иначе старый файл с 0 будет выглядеть как успех нового прогона, которого ещё нет.

2.3 Задачи продукта

Пока идёт установка, часть работы живёт в задачах (taskmgr). Их состояния читаются в GUI (раздел задач) или через Model API. Практические значения:

Состояние Смысл
SUCCESS задача дошла до конца
FAILURE задача упала; смотреть taskmgr/playbooks.log
QUEUED задача ждёт; при падении фазы остаётся висеть
NOTCONFIGURED приложение/узел не сконфигурирован

Если фаза упала, узел остаётся NOTCONFIGURED, упавшее приложение — тоже NOTCONFIGURED, остальные подзадачи — QUEUED. Это не «зависло», а остановленный конвейер.


3. pgrep и ложные «жив»

Проверка «процесс жив» ломается на самой себе:

pgrep -f install-ng.py      # матчит вашу же строку запуска → ложное «жив»
pgrep -f "[i]nstall-ng.py" # скобки исключают сам pgrep и вашу команду
pgrep -af install-ng.py     # покажет, что именно нашлось

pgrep -f ищет по полной командной строке, а вы только что эту строку и набрали. Поэтому в скриптах и в ручных проверках используют [i]nstall-ng.py: шаблон [i] совпадает с буквой i в чужой командной строке, но не с текстом самого шаблона.

Второй ложный «жив» — процесс-сирота после обрыва SSH. Маркер при этом не появился, лог не двигается. Проверка: pgrep -af install-ng.py плюс stat -c %y /opt/ampli/var/log/marvin/install.log — если mtime не меняется минутами, процесс не работает, а висит.


4. HTTP-коды как маркеры

Часть состояний продукта читается только кодом ответа. Ниже — те, что действительно различают «работает» и «не работает».

Код Где Что значит
307 + Server: Quantum-ActiveScale http://127.0.0.1/ (443) S3-фронт жив; редирект штатный
200 /model/... на 8443 под root Model API отвечает
000 8443 без sudo не предъявлен клиентский сертификат, а не «API лёг»
400 пустой GET на 8180 iamd жив, ждёт корректный запрос
200 быстрее 50 мс /federated/_status/ федерация здорова
30000 мс / таймаут /federated/_status/ pymongo topology-hang: порт/конфиг федерации, не «умерла БД»
404 /federated/_status/ локация не отрендерена: федеративная БД не создавалась
400 PUT в модель нет заголовка Content-Type: application/json
500 -C / политика пустая колонка или неверный category политики
501 Tape Connector по 443 запрос ушёл не туда (URL без порта → фронт S3)
403 S3-клиент подпись/часы (SigV4), а не права
507 S3 PUT политика не влезает в число блоксторов (w+s > N)

Логика простая: сначала код, потом смысл. 403 при зелёном GUI — это почти всегда часы, а 507 при свободных дисках — политика, а не ёмкость.


5. Коды полевого health-check

Наш скрипт быстрой проверки узла (as-field-health.sh, только чтение, около 30 секунд на узел) возвращает:

  • 0 — ни одного FAIL;
  • 1 — есть хотя бы один FAIL.

[warn] сам по себе прогон не валит: это повод посмотреть, но не поломка. Так сделано намеренно: иначе скрипт краснел бы на известных ложных тревогах и им перестали бы пользоваться.


6. Ловушки маркеров

  1. Старый маркер не удалён. Файл /tmp/.unattended_install_finished с прошлого прогона даёт «готово» через секунду после старта. Удалять до запуска.
  2. Пустой install.log после полуночи. Это logrotate: смотреть install.log.YYYY_* и taskmgr/playbooks.log, а не делать вывод «лог не пишется».
  3. Код 0 у фазы, которая ничего не сделала. Сверять не код, а объекты в модели и гейты.
  4. Маркер без процесса. Файл мог остаться от оборванного прогона; проверять pgrep и mtime лога одновременно.
  5. «Задача QUEUED» ≠ «задача идёт». После падения фазы очередь стоит; смотреть taskmgr/playbooks.log на TASK [...], PLAY RECAP, failed=.

7. Чек-лист «завершилось ли»

  1. pgrep -f "[i]nstall-ng.py" → пусто (процесса нет).
  2. cat /tmp/.unattended_install_finished → код есть, и он ожидаемый.
  3. /opt/ampli/var/log/marvin/install.log → последняя запись соответствует концу фазы, нет _error.
  4. /federated/_status/ → 200 быстрее 50 мс.
  5. pgrep -c mongod → по числу кластеров на каждой ноде.
  6. Приложения → NOTCONFIGURED = 0.
  7. S3 PUT/GET → round-trip, GUI без пустот, новых CRITICAL в событиях нет.

Только после этих семи пунктов прогон считается завершённым.


8. Источники

  • Software Documentation Center (7.3) (дата доступа 2026-11-07)
  • Наша практика (обезличено): прогоны stage 0–3 на 3-нодных стендах, разбор ложных «жив» и маркеров завершения.

Нужен инженер? Разберу вашу ситуацию и скажу, что делать — по шагам, с проверками.

Обсудить задачу