Эксплуатация OpenClaw 25 апреля 2026

2026: буферизация stdio OpenClaw, остановки JSON-RPC MCP и обратное давление канала на арендованном ProxyMac Mac mini

Инженерная команда ProxyMac 25 апреля 2026 ~11 мин чтения

На ProxyMac Mac mini в Гонконге, Японии, Корее, Сингапуре или США OpenClaw часто регистрирует MCP-серверы поверх stdio: шлюз порождает дочерний процесс, говорит JSON-RPC через stdin/stdout и ждёт, что каждое сообщение придёт сразу. Сбой выглядит зловеще тихо: первый вызов инструмента работает, затем ребёнок перестаёт что-либо выводить, хотя top показывает простой CPU. В девяти случаях из десяти виноваты не «плохие модели», а буферизация stdio плюс обратное давление канала: процесс переходит в полностью блочно буферизованный режим, потому что больше не видит TTY; частичные ответы сидят в libc, пока буфер не заполнится. Родитель может блокироваться на read(), ожидая разделитель, который не придёт, или ребёнок блокируется на write(), потому что родитель не опустошил канал. Руководство описывает архитектуру, сопоставляет построчную и блочную буферизацию с матрицей симптомов, сравнивает PTY-обёртки и «голые» каналы под launchd, перечисляет меры для Python (PYTHONUNBUFFERED=1, python -u), фильтров POSIX (stdbuf -oL) и потоков Node (держите stdout в потоковом режиме), затем даёт пятиступенчатую диагностику, связанную с развёртыванием MCP, перезапуском шлюза, устранением проблем развёртывания и ulimits, когда на самом деле истощение дескрипторов маскируется под «зависания».

Архитектура MCP stdio в macOS (что должно оставаться истинным)

Представьте три сотрудничающих процесса: (A) шлюз OpenClaw, (B) бинарник или скрипт MCP-сервера, (C) опциональные фильтры (jq, рантаймы). Любой участник, который блокируется на записи, пока другой ждёт чтения в той же циклической зависимости, создаёт взаимоблокировку. Транспорты stdio наследуют и дисциплину stderr: болтливые библиотеки, сыплющие прогресс-бары в stderr, могут заполнить буферы канала ядра, если их никто не читает.

  • Ожидать одно JSON-сообщение на каждый сброс нереалистично — libc не знает границ JSON.
  • Большие ответы требуют потоковых читателей; если шлюз буферизует весь полезный груз в RAM, вы почувствуете «остановки», не связанные с семантикой MCP.
  • launchd не подключает ваши интерактивные shell-rc — паритет окружения ручной; см. шаблоны upgrade/rollback для упорядоченных перезапусков после смены окружения.

Построчная и блочная буферизация (почему Terminal «работает»)

Многие CLI используют построчную буферизацию, когда isatty(stdout) истинно, и блочную (часто кратно 4–8 KiB), когда stdout — канал. Под безголовым LaunchAgent ваш MCP-сервер внезапно становится писателем в канал — логи, которые в Terminal казались «живыми», пакуются, пока буфер не заполнится. Задержка выглядит как «модель остановилась», хотя LLM закончил секунды назад.

Совет по инструментированию: на время диагностики оборачивайте подозрительные команды stdbuf -oL -eL — измерьте задержку, прежде чем вшивать обёртки в продуктовые plist.

Матрица симптомов зависшего MCP

СигналВероятнее багов MCPПодтвердить / опровергнутьСледующая ссылка
Первый RPC ок, второй висит навсегдаБлочно буферизованный stdoutТот же бинарник под script -q /dev/null (дымовой PTY-тест)Эта статья
CPU забит, RAM ровнаяТугой спин на пустом fdСэмпл sample pid 5 -file /tmp/st.txtДиагностика
Too many open filesUlimits, fan-out MCPlaunchctl limit maxfiles против мягкого лимита процессаUlimits
Интермитентно после ротации логовОбработка SIGHUP / переоткрытые fdСопоставить метки времени с newsyslogЛоги

PTY-обёртки и «голые» каналы под LaunchAgents

Некоторые команды оборачивают MCP-серверы в script, unbuffer или кастомные PTY-родители, чтобы дети думали, что они интерактивны. Компромисс: PTY добавляют накладные расходы CPU и копирования, но убирают класс сюрпризов буферизации. Голые каналы дешевле, но требуют дисциплинированного сброса в дочернем процессе или прокладок stdbuf. Выбирайте осознанно — смешение стилей между серверами путает дежурных.

Безопасность: PTY не дают доверия — по-прежнему применяйте белые списки инструментов из развёртывания MCP и гигиену секретов из усиления Keychain.

Смягчения в цепочке инструментов (скопировать в EnvironmentVariables LaunchAgent)

Python: экспортируйте PYTHONUNBUFFERED=1 или вызывайте python3 -u; для упакованных CLI предпочитайте точку входа с sys.stdout.reconfigure(line_buffering=True) на поддерживаемых версиях. Node: потребляйте stdout в потоковом режиме — приостановленные потоки между дочерними процессами — частая ловушка. Go / Rust: явно сбрасывайте буфер после каждого кадра JSON-RPC, если контролируете исходники. Shell-фильтры: в автоматизации через каналы не забывайте grep --line-buffered.

<key>EnvironmentVariables</key> <dict> <key>PYTHONUNBUFFERED</key> <string>1</string> <key>NODE_OPTIONS</key> <string>--max-old-space-size=4096</string> </dict>

Пятиступенчатая stdio-диагностика до переписывания агента

  1. Воспроизведение под ssh: те же ProgramArguments из plist вставить в интерактивный shell — если внезапно заработало, есть расхождение окружения/TTY.
  2. Аналог strace в macOS: кратко sudo fs_usage -w -f filesys | grep mcp для зависших записей (в проде осторожно).
  3. Разделить stderr в ротируемый файл, чтобы отладочный шум не конкурировал с JSON-RPC на stdout.
  4. Нагрузочный прогон с синтетическими крупными полезными нагрузками после включения смягчений.
  5. Выбрать транспорт: если stdio остаётся хрупким, планируйте HTTP MCP по руководству по развёртыванию.

FAQ

Помогает ли увеличение sysctl буфера канала? Только крайний случай — чаще причина в несогласованном ритме читателя и писателя, а не только в размере буфера.

Стоит ли логировать MCP-серверам в stdout? stdout только для JSON-RPC; человеческие логи — в stderr или структурированные файлы.

Меняет ли Apple Silicon буферизацию? Нет — M4 лишь ускоряет столкновение с багом, но не делает иммунитетом к умолчаниям libc.

Почему ProxyMac Mac mini — правильное место, чтобы укрепить MCP stdio

Мини Apple Silicon M4 в регионах HK / JP / KR / SG / US дают постоянно включённое железо, где можно ночью повторять одни и те же графики stdio, подвесить региональную ёмкость рядом с вызываемыми SaaS API и держать ссылки справки возле репозитория LaunchAgent. Когда людям нужно подтверждать запросы TCC, откатитесь на VNC; когда сеть добавляет колебания, читайте IPv6 Happy Eyeballs SSH из той же линии релизов.

Запускайте OpenClaw на железе, которое можно спокойно strace’ить

HK / JP / KR / SG / US · автоматизация, дружественная к stdio