Иллюстрация про шлюз OpenClaw, launchd и удалённый Mac

OpenClaw на macOS: когда openclaw gateway restart успешен, а слушатели остаются старыми

Этот материал опирается на официальную лестницу диагностики и дополняется руководством по установке, переустановке и launchd, split-brain, lastTouchedVersion и deep path, удалённый шлюз, CLI-дрейф и health-probe, канал онлайн, зелёный probe, 429 и credentials doctor, регрессии памяти, session jsonl и rollback, Docker Compose, токен-авторизацию и нажим WebSocket-парирования.

Команды, которые держат OpenClaw на удалённых Mac, всё чаще воспринимают gateway как единый долгоживущий слой для доставки расширений, health‑probe и повторного pairing. Самый раздражающий сценарий в 2026 году всё тот же: `openclaw gateway restart` возвращает ноль, логи вежливы, а слушатели, unix‑сокеты или админ‑заголовки остаются на вчерашней сборке. Это редко «магия сети» — чаще `launchd` держит пользовательский LaunchAgent с устаревшими `ProgramArguments`, неверным `WorkingDirectory` или закэшированным окружением, пока CLI перезапускает лишь дочерний процесс.

Неинтерактивный SSH и GUI‑сессия консольного пользователя наследуют разный PATH и разную видимость связок ключей. Перезапуск из вашей интерактивной оболочки может выглядеть успешным, тогда как агент всё ещё стартует бинарь по абсолютному пути, который должен был смениться после апгрейда. Поэтому `plutil -p` для `~/Library/LaunchAgents/com.openclaw.gateway.plist` — обязательный шаг после каждого окна обновления.

Прежде чем трогать `bootout`, пройдите официальную лестницу диагностики и сохраните артефакты с меткой времени. Она отделяет расширения, лимиты 429, учётные данные и чистую дрейф‑историю `launchd`. Пропуск уровней сжигает часы и маскирует внешние инциденты, которые совпали по времени с вашими попытками recycle.

Метка `com.openclaw.gateway` — источник правды о том, что реально стартует при логине и bootstrap. Современный macOS требует доменно‑осознанных глаголов `launchctl`. Пара `bootout` и `bootstrap` для plist восстанавливает таблицу агентов; один лишь `kick` может оставить уже материализованные аргументы неизменными, отсюда «стейл»‑листенеры при нулевом коде выхода.

Если метаданные разошлись с установленным layout, уместен `gateway install --force`, но только после резервного копирования токенов, JSON pairing и пользовательских деревьев расширений. Согласование semver между CLI, бинарём gateway и персистентными метаданными снимает split‑brain, который выглядит как «рестарт не помогает».

Пакеты расширений — часть версионного контракта. Новый core со старым API расширений даёт полу‑успехи, похожие на зависшие порты. Фиксируйте поверхности admin‑listener против LAN, особенно если Compose или межсетевой экран macOS публикуют интерфейсы иначе, чем ожидает CLI.

Для docker‑смежных стеков синхронизируйте опубликованные порты и секреты WebSocket с матрицей сопряжения. Локальный recycle может быть успешен, пока reverse‑proxy держит старый upstream. К доказательствам добавьте четыре факта: ожидаемая semver, фактическая semver, mtime plist, экспорты официальной лестницы.

Инвентаризируйте TCP, unix‑сокеты и ожидаемые пространства имён. Если restart не меняет слушателей, привязанный процесс, вероятно, не тот. Сравнивайте отпечатки или версии между бинарём, который вызывает CLI, и тем, что прописан в LaunchAgent, пока не сойдётесь в коридоре semver, принятом в организации.

Тихие откаты случаются, когда новый бинарь записан, а старый wrapper остался. CLI может казаться свежим, пока `launchd` всё ещё `exec`ит устаревший shim — нужна форензика, а не цикл рестартов.

Классифицируйте инциденты по окну обновления: свежие кластеры намекают на неполные миграции метаданных LaunchAgent; спорадический дрейф — на ручные правки plist или неаккуратную автоматизацию. Разделяйте пользовательский эффект и эффект для оператора: клиенты могут ломаться по auth, если секреты WebSocket ротировались, а слушатели держат старые значения.

Когда расширения «загружены», но поведение не меняется, фиксируйте версии манифеста отдельно от core. Preview‑каналы и смеси npm/vendor усиливают риск. Сначала читайте канальный runbook: осцилляции 429 имитируют «мёртвый» демон.

После `bootstrap` убедитесь, что job в нужном GUI‑домене, а не в эфемерном домене SSH. Удалённые админы часто путают домены `sudo` и пользователя. Делайте diff plist между здоровым и больным хостом при расхождении флота.

Хозяйство: дубли `Disabled`, сиротские throttle‑интервалы, наследуемые `KeepAlive` могут принимать сигналы restart, удерживая дескрипторы старых extension‑хостов. Избегайте правок XML через `sed`; версионируйте шаблоны plist на релиз и проверяйте хэши.

Операционализируйте baseline после восстановления: выдержки semver, отпечаток plist, `launchctl print` для `com.openclaw.gateway`, инвентарь слушателей, doctor, минимальные и глубокие пробы. Архивируйте вместе с идентичностью хоста и каналом релиза. Недельные диффы ловят медленное гниение вроде изменённого PATH от новых dev‑инструментов.

Разделяйте «SSH работает» и «gateway стабилен». Экранный шаринг и MDM иногда дают shell без гарантий GUI‑агентов. Бэкапы перед force‑install должны быть проверены на восстановление, а не декоративны. Включайте алерты из канальных гайдов, включая классы 429, которые сигналят про throttling провайдера, а не про локальные стейл‑листенеры.

Опишите цепочку эскалации на одной странице: владелец лестницы, платформа для `bootout`, security для ротации токенов, release для окон force‑install. Гигиена тикетов оправдывает бюджет, когда финансы спрашивают про часы Mac. Парное обучение на staging с реальными слушателями до прод‑инцидентов.

Ежеквартально проводите контролируемые инъекции сбоев на непрод‑клонах, чтобы не рисковать выручкой. Структурированные логи важнее галерей скриншотов.

Пара semver — не роскошь: конфликты `lastTouchedVersion` и дрейф глубоких путей дают зелёные баннеры при сломанном поведении. Централизуйте апгрейды с checksum и post‑install hook, который сверяет `ProgramArguments` с установленным бинарём. Если патч‑трейн регрессирует, смотрите rollback раньше, чем бесконечно форсировать вперёд.

Удалённое управление требует воспроизводимых доказательств при лаге screen sharing. Официальная лестница даёт эти доказательства, если её не пропускать. `bootout`/`bootstrap` на `~/Library/LaunchAgents/com.openclaw.gateway.plist` выравнивает `launchd`; `gateway install --force` пересобирает артефакты инсталлятора, когда метаданные реально потеряны.

Сброс pairing — последний рычаг, когда слушатели новые, а клиенты видят старые секреты. Согласуйте простои. Для Compose синхронизируйте websocket‑секреты и опубликованные порты с матрицей сопряжения, чтобы не получить ложный успех.

FAQ: ноль выхода не значит, что `launchd` перечитал plist; `bootout` кратко рвёт слушание — анонсируйте окно; force‑install не лечит аварии провайдера; поверхностные healthchecks остаются зелёными, пока аутентифицированные маршруты старые; не удаляйте plist без плана замены.

Вывод: трактуйте инцидент как разрыв контракта между регистрацией `launchd` и фактическим layout установки. Пройдите официальную лестницу, детерминированно почините `com.openclaw.gateway`, эскалируйте к force‑install с дисциплиной бэкапов, закрепите semver‑пару в мониторинге. Для предсказуемой удалённой ёмкости смотрите хостинг SFTPMAC рядом с цитируемыми runbook.

Дополнительно по governance: запретите `bootout` без экспорта лестницы. Хуки тикетов могут требовать doctor‑вывод, канальную пробу и хэш plist. Это снижает ночные регрессии «на глаз».

Смешанные Linux/macOS флоты требуют общей semver‑политики в репозиториях. Linux с новой CLI и macOS LaunchAgent на старом gateway порождают тикеты, где обе стороны «зелёные», отвечая на разные вопросы. Централизуйте матрицу версий и прокидывайте её через CI‑лейблы.

Тренируйте восстановление токен‑экспортов в изолированной учётке. Если restore падает, rollback force‑install неполон. Явно перечисляйте файлы, которые нельзя версионировать, чтобы не утекли секреты в тикеты, но оставались метаданные для дрейфа.

Следите за событиями ФС на plist: менеджеры конфигураций иногда пишут атомарно. В редких гонках `launchd` видит частичное состояние; `bootout` после атомарной замены безопаснее серии `kick`.

Встройте release notes вендора в post‑install чеки. Если релиз переименовывает ключи LaunchAgent, ваш Ansible/Chef должен повторить переименование. Иначе старый ключ жив, пока CLI уже ждёт новые дефолты.

Для саппорта сделайте макросы с четырьмя фактами: ожидаемая semver, фактическая semver, mtime plist, экспорт лестницы. Это укорачивает triage и останавливает слепые рестарты.

С reverse‑proxy проверяйте sticky‑сессии и websocket upgrade отдельно от `launchd`. Рестарт gateway бесполезен, если прокси кэширует старый upstream — добавьте proxy‑логи в тот же evidence‑пакет.

Планируйте окна обслуживания так, чтобы `bootout` не попадал на загрузку расширений. Обрывы загрузок оставляют полуфабрикаты, мигающие зелёным/красным и похожие на стейл‑листенеры.

Закрывайте инцидент только если матрица считает `bootstrap` достаточным и лестница не показывает 429/учётные предупреждения. Иначе фиксируйте остаточный риск вместо маскировки новым restart.

Культура эксплуатации: учите новичков читать ноль выхода скептически, иначе закрепляется привычка повторять команды вместо сравнения состояний. Добавьте песочницу с намеренно устаревшим plist.

Когда финансы спрашивают про часы Mac, покажите экономию времени за счёт стандартизированных артефактов лестницы. Документируйте цену ошибки домена: неверный `bootout` может стоить дольше ремонта, если GUI‑агент остался нетронутым.

Автоматизируйте алерты на расхождение `lastTouchedVersion` и строки бинаря. Ежедневный diff ожидаемой и заявленной версии ловит дрейф раньше пользователей.

Наконец, относитесь к OpenClaw на macOS как к двойной истине: layout пакетного менеджера и регистрация `launchd`. Пока они не синхронны, `openclaw gateway restart` будет вежливо успешен, а клиентская реальность упрямо стара. С официальной лестницей, чистым `bootout`/`bootstrap`, дисциплинированным force‑install и semver‑платформа снова становится скучной — а скука — высший комплимент инфраструктуре.

Практическое расширение: журналируйте каждую попытку restart с цепочкой родительских PID и открытыми сокетами до вмешательства в `launchd`. Так видны обёртки, которые порождают детей, унаследовав дескриптор родителя. На Apple Silicon следите за смешением Rosetta: arm64‑бинарь под x86_64‑shim даёт «свежую» CLI при старом агенте.

Держите переменные окружения в plist явно, а не через наследование. SSH часто задаёт иные локали и токены, чем GUI; без `EnvironmentVariables` restart завершится без ошибки, но расширения останутся без ключей API. Сверяйте с вендорским шаблоном.

Для CI‑раннеров на удалённых Mac избегайте совместного окна обновления Homebrew и вендорского пакета. `brew cleanup` может удалить промежуточные версии, на которые ещё ссылается `launchd`, порождая «призрачные» пути.

Используйте пробы, бьющие по аутентифицированным endpoint’ам, а не только loopback‑пингам. Поверхностные пробы объясняют зелёные дашборды при старых политиках на аутентифицированных маршрутах. Сочетайте с матрицами дрейфа удалённого CLI.

Планируйте `gateway install --force` со списком ожидаемых файловых диффов: какие ключи plist переписываются, какие лог‑пути пересоздаются, какие кэши расширений чистятся. Без списка любое отклонение после установки выглядит как регрессия.

WebSocket‑pairing требует совместного выката секретов и слушателей. Ротация секретов без recycle сокетов оставляет клиентов несогласованными при успешных CLI‑рестартах. Матрица Compose описывает зависимость — не игнорируйте её при участии sidecar.

На разборе инцидента спросите: полный экспорт лестницы? верный bootstrap‑домен? согласованы ли хэши между CLI‑префиксом и LaunchAgent? есть ли пики 429 в каналах? Без ответов force‑install — театр, не терапия.

Стандартизируйте ZIP‑пакеты доказательств (plist, `launchctl print`, semver, транскрипты проб, порты Compose). Это ускоряет аудит и онбординг и снимает давление ночных импровизаций `bootout`.

Учитывайте термодросселирование на стоечных Mac: под нагрузкой `launchd` может откладывать перезапуски, имитируя зависшие слушатели. Замеряйте температуру CPU и ожидания диска, прежде чем обвинять launchd.

Обучайте операторов сомневаться в нуле выхода. Иначе закрепляется культура повторения команд вместо сравнения состояний. Добавьте песочницу с устаревшим plist.

Когда финансы спрашивают про часы Mac, покажите выигрыш времени за счёт стандартизированных артефактов. Документируйте цену ошибки домена: неверный `bootout` может длиться дольше ремонта, если GUI‑агент остался нетронутым.

Автоматизируйте алерты на расхождение `lastTouchedVersion`/бинаря. Ежедневный diff ловит дрейф раньше пользователей.

1. Симптомы при видимом успехе

Нулевой код выхода не равен health-check. Пользовательский LaunchAgent может обновить обёртку, оставив старые сокеты.

Частичные перезагрузки маскируют проблему: doctor зелёный, глубокие маршруты отдают старую политику.

2. Официальная лестница до launchd

Пропуск уровней смешивает расширения, 429, учётные данные и чистый дрейф launchd.

Фиксируйте каждый шаг с меткой времени для передачи смены.

3. plist, bootout и bootstrap

`~/Library/LaunchAgents/com.openclaw.gateway.plist` должен указывать на актуальный бинарь. После правок предпочитайте `bootout`/`bootstrap` вместо неоднозначного `kick`.

4. Нумерованный чек-лист

  1. Соберите ожидаемую semver, фактическую semver, mtime plist и выгрузки лестницы.
  2. Пройдите официальную лестницу до любых операций launchd.
  3. Проверьте `ProgramArguments` через `plutil -p`.
  4. Выберите корректный bootstrap-домен, выполните `bootout`, затем `bootstrap`.
  5. Отфильтруйте `launchctl print` по `com.openclaw.gateway` и сверьте пути.
  6. При расхождении layout сначала сохраните токены, затем рассмотрите `gateway install --force`.
  7. После выравнивания повторите поверхностные и глубокие пробы.
# 1) Сначала официальная лестница (doctor, пробы, расширения)
#    См.: 20260506-openclaw-ofitsialnaya-lestnitsa-diagnostiki-gateway-probe-rasshireniya-429-rukovodstvo-2026-ru.html

# 2) Проверить пользовательский LaunchAgent
/usr/bin/plutil -p ~/Library/LaunchAgents/com.openclaw.gateway.plist

# 3) Подставить DOMAIN и перерегистрировать
/usr/bin/launchctl bootout DOMAIN ~/Library/LaunchAgents/com.openclaw.gateway.plist || true
/usr/bin/launchctl bootstrap DOMAIN ~/Library/LaunchAgents/com.openclaw.gateway.plist

# 4) Проверить label com.openclaw.gateway
/usr/bin/launchctl print DOMAIN | /usr/bin/grep -n "com.openclaw.gateway" || true

# 5) Если ProgramArguments всё ещё неверен — после бэкапа
#    openclaw gateway install --force

5. Матрица решений

Выбирайте минимальное действие, восстанавливающее инварианты.

Вмешательство Когда уместно Плюс Риск
openclaw gateway restart Лёгкое перечитывание без смены путей Быстро, малый радиус Может не обновить ProgramArguments
bootout / bootstrap Устаревшая таблица агентов или свежий plist Пересобирает регистрацию Неверный домен даёт тихий провал
gateway install --force Дрейф shim или неполный апгрейд Понятные артефакты установщика Нужна дисциплина бэкапов
Сброс pairing/секретов Слушатели новые, клиенты со старой auth Снимает split-brain Нужна координация простоя

6. Сопряжение semver и удалённый дрейф

CLI, шлюз и персистентные метаданные должны двигаться набором. Расхождения `lastTouchedVersion` выглядят как «рестарт не сработал».

Удалённые флоты обновляются с разной скоростью — автоматизируйте проверку путей plist после каждого выката.

7. Базовая линия удалённого Mac

После восстановления архивируйте semver, отпечаток plist, выдержку `launchctl print`, инвентарь слушателей, doctor, минимальные и глубокие пробы.

Запускайте еженедельно и после изменений toolchain.

8. Нумерованные болевые точки

  1. Нулевой выход и несовпадение поколения заголовков.
  2. Путаница GUI-домена и SSH-домена.
  3. Semver кажется ровным, а поверхность расширений старая.
  4. Токены новые, слушатели держат старые секреты.

9. FAQ

Вопрос: Сразу `bootout`? Ответ: Короткий простой; сначала исключите 429 и учётные данные.

Вопрос: `gateway install --force` панацея? Ответ: Помогает при рассинхроне установки, не при аварии провайдера.

Вопрос: Почему health остаётся зелёным? Ответ: Поверхностные пробы; углубите аутентифицированные маршруты.

10. Заключение и хостинг

Рассматривайте инцидент как разрыв между регистрацией `launchd` и фактическим layout: лестница, `bootout`/`bootstrap`, дисциплинированный force-install, semver-пара.

Стандартизированные доказательства ускоряют разбор и снижают ночные сюрпризы.

Для предсказуемой удалённой ёмкости изучите тарифы хостинга удалённых Mac SFTPMAC вместе с цитируемыми runbook.