DevOps и аудит 27 апреля 2026 г.

OpenClaw launchd: ThrottleInterval, KeepAlive и health-пробы — матрица 2026 на арендованном Mac mini

Команда инженеров VmMac 27 апреля 2026 г. ≈ 23 мин чтения

Платформенные инженеры, запускающие OpenClaw под LaunchAgent на арендованном Mac mini Apple Silicon у VmMac, наследуют тонкие значения по умолчанию: ThrottleInterval скрывает циклы падений, KeepAlive воскрешает «отравленные» процессы, а семантика SuccessfulExit может расходиться с выходами Node во время обновлений. Матрица 2026 называет безопасные сочетания, показывает ложноположительные бури перезапусков, перечисляет headless-паттерны health-проб и связывает наблюдаемость с паритетом в Гонконге, Японии, Корее, Сингапуре и США. Читайте вместе восстановление шлюза, изоляцию staging и production и структурированные логи и ротацию диска, чтобы правки plist не превращались в угадайку.

Базовые пути: руководство по установке и развёртыванию; доступ: справка; отдельные canary-хосты: цены. Пики Spotlight/mds сопоставляйте с матрицей индексации и CI-диска, прежде чем винить OpenClaw.

Почему политика launchd важнее версии бинарника Node

Идеально зафиксированный semver OpenClaw бессилен, если launchd перезапускает шлюз каждые 12 секунд, потому что health-проба принимает задержку LLM за смерть процесса. Ключи plist — часть SLA: они задают, как ОС интерпретирует успех, ошибку и откат. Без гипервизорного супервизора у VmMac супервизор — launchd.

Node-шлюзы наследуют сигнальную семантику macOS: SIGTERM при деплое должен закрыть HTTP-серверы, сбросить структурированные логи и завершиться до эскалации launchd к SIGKILL. Если процесс игнорирует SIGTERM из‑за зависшего upstream WebSocket, в интерактивной оболочке видны «успешные» ручные рестарты, а у агентов — «дрожь». Задокументируйте ожидаемую лестницу сигналов в том же README, где закреплён Node LTS, и отрепетируйте на одноразовом mini VmMac до правок продовых plist.

ThrottleInterval не заменяет исправление багов — меняется лишь громкость сбоев. Сочетайте откат на уровне ОС с прикладными circuit breaker’ами, чтобы отравленная конфигурация модели не грузила CPU во всех регионах. По умолчанию одинаковые числа в Гонконге, Токио, Сеуле, Сингапуре и США; исключения — только письменно обоснованные эксперименты по задержке.

  • ThrottleInterval ограничивает частоту рестартов, но может маскировать длительные частичные отказы.
  • KeepAlive держит демоны резидентными, но усложняет draining при обновлениях.
  • ExitTimeOut задаёт бюджет graceful shutdown до SIGKILL.

Матрица: ThrottleInterval vs KeepAlive vs ExitTimeOut

Цель Основная ручка Риск Смягчение
Остановить crash-loop ThrottleInterval ≥ 30 с Медленнее восстановление после реальных падений Внешний пейджинг по коду выхода
Всегда включённый шлюз KeepAlive true + SuccessfulExit false Respawn при намеренном shutdown Отдельный maintenance-label
Graceful drain ExitTimeOut 25–40 с Зависший shutdown блокирует рестарт SIGKILL watchdog после бюджета
Избежать стада после reboot Разнесённый StartCalendarInterval или случайный sleep в обёртке Задержка готовности относительно пиров Health-gate ждёт зависимости, не настенные часы

Совместное размещение с другими агентами launchd: рассмотрите plist-Nice и LowPriorityIO, чтобы лог-шиппер не голодал цикл событий шлюза. Это не планирование ёмкости, но даёт минуты при частичных инцидентах — часто хватает, чтобы осознанно расширить ThrottleInterval.

Ложноположительные бури перезапусков: симптомы и причины

Бури часто начинаются, когда health бьёт в localhost, пока шлюз ещё не забиндил сокеты после дискового давления, замедлившего загрузку модулей. Другой шаблон — всплески Spotlight/mds, удлиняющие cold start сверх таймаута пробы — коррелируйте с политикой индексации.

Предохранитель: не задавайте интервал пробы короче cold-start p95 без прогрева.

Флаппинг зависимостей: если проба проверяет внешний SaaS до готовности loopback, микрорывки маршрутизации в Японии или Сингапуре помечают шлюз больным при живом процессе. Разделите пробы: сначала loopback, внешний canary — опционально с мягче таймаутами.

Полный диск: JSONL до ENOSPC, ненулевой выход, KeepAlive поднимает процесс, логи снова падают — иногда быстрее, чем ThrottleInterval остужает систему. Зеркалируйте дисковые предохранители из структурированной ротации логов.

Headless health-пробы без VNC

Небольшая обёртка curl’ит health-порт на loopback — проверку TLS отключайте только на loopback — или лучше CLI status OpenClaw. После пробы логируйте HTTP-статус, мс TLS-handshake и PID, чтобы дежурный отличил «процесс жив, но завис» от «процесс мёртв».

По возможности шлите синтетический заголовок X-Probe-Trace-Id и эхом в логах шлюза — это сшивает сбои пробы с медленными запросами сильнее любого твика plist.

curl -fsS --max-time 3 http://127.0.0.1:18789/health || exit 1

Восьмишаговая лестница настройки на 2026 год

  1. Семь дней собирать базовые коды выхода до смены plist.
  2. Выставить ThrottleInterval, остановив паттерн рестартов <20 с.
  3. Согласовать ExitTimeOut с документированным SLA graceful shutdown.
  4. Добавить структурированные логи на каждую причину рестарта.
  5. Canary 72 ч в одном регионе VmMac.
  6. Сравнить счётчики рестартов HK, JP, KR, SG, US.
  7. Задокументировать откат plist в git-теге launchd-YYYYMMDD.
  8. Квартальный game day: kill -9 и измерить восстановление.

Между шагами четыре и пять заморозьте фичи на canary-лейбле на 72 часа, даже если метрики зелёные — многие бури видны только в выходной форме трафика. Сохраняйте sample и footprint в окне canary для регрессий памяти между регионами.

Статьи про восстановление говорят, что перезапускать; эта матрица — когда ОС должна перезапускать за вас. При расхождении цифр люди теряют доверие и привыкают к kill -9. Держите одинаковые числа в staging и prod согласно изоляции staging, чтобы промоушны были diffable.

Числовая привычка: пейджить, если рестарты >6 в час дольше 20 минут — это почти никогда «нормальная дисперсия LLM».

Таблица наблюдаемости: поля на каждый рестарт

Поле Назначение
launchd_exit_status Отличить OOM от чистого выхода
uptime_s Петли младенческой смертности
rss_mb Утечки до SIGKILL
fds_open Утечки дескрипторов, усиленные keepalive
last_http_5xx_ts Разделить upstream и локальную смерть

Отправляйте поля JSONL в тот же sink, что и запросы шлюза, чтобы SRE переходил от «launchd перезапустил job» к «RSS превысил 1,2× базы». Согласованные имена в Гонконге, Японии, Корее, Сингапуре и США важнее идеальной кардинальности в первой итерации.

FAQ: launchd и OpenClaw на Mac mini

LaunchDaemon вместо LaunchAgent? Только после явного security-review — агенты наследуют границы TCC пользователя.

Тюнинг по регионам? Только с письменными исключениями; по умолчанию паритет.

Апгрейды? Временно расширяйте ThrottleInterval на npm-миграциях.

SuccessfulExit false всегда означает «рестарт на любой выход»? По сути да для большинства шлюзов — добавьте коды выхода drain vs crash.

Пробы от root? Предпочитайте тот же пользовательский контекст, что и у шлюза.

Заглушить алерты на обслуживание? Файл обслуживания в обёртке с автоистечением.

Почему Mac mini M4 и VmMac подходят для always-on шлюзов

Mac mini M4 даёт достаточно устойчивой производительности, чтобы пережить редкие cold start без ложных срабатываний агрессивных проб; unified memory снижает OOM-флапы относительно переподписанных VPS. VmMac размещает шлюзы в Гонконге, Японии, Корее, Сингапуре и США рядом с пользователями и требованиями резидентности данных — второй mini для экспериментов с plist без риска для продовой семантики рестартов.

Аренда сокращает цикл обратной связи, когда Apple в патчах macOS незаметно меняет launchd: снимите снапшот матрицы plist, примените патч на непрод mini, повторите тот же health-harness, затем трогайте клиентскую автоматизацию. Дешевле одной ночной страницы из-за недокументированной политики рестартов.

Канареечный plist перед продом

Арендуйте ещё один Mac mini VmMac в Сингапуре или Токио, чтобы проверить ThrottleInterval без ночных звонков.