openclaw doctor, 기본 포트 18789의 TCP 리스너 지문(lsof)을 한 파이프라인에 묶어 재현 가능한 CI 전제 게이트를 돌리려는 운영·플랫폼 팀.단일 URL 예: 2026-openclaw-gateway-status-json-doctor-ci-gate-remote-mac.html (본 문서)
연관: config validate CI 게이트, 게이트웨이 임베딩·RAG 프리페치, 비대화형 onboard·병합 로그 HowTo. 로그인 없이 열람 가능합니다.
원격 Mac에서 게이트웨이를 안정적으로 돌릴 때의 가치
전용 원격 Mac에서 의존성 프리풀을 먼저 하면 gateway status·doctor가 콜드 스타트가 아닌 지연을 보여 줍니다. gateway-status.json과 로그를 아티팩트로 묶으면 재기동 없이 Slack·Checks에 짧은 CI 요약만 실을 수 있습니다.
이 연쇄가 없을 때 흔한 문제
- 사람만 보는 점검: SSH로 들어가 예쁜 텍스트만 훑으면 JSON 필드로 잡을 수 있는 회귀를 놓칩니다.
- 포트 유령: 어제 실험으로 남은 리스너가
18789를 잡고 있어도, doctor만으로는 TCP 점유와 항상 일치하지 않을 수 있습니다. - PATH 허구: CI는
nvm셸 shim을 쓰고launchd는 다른node를 쓰면, 게이트는 통과했는데 운영 데몬은 예전 바이너리를 물고 있습니다.
무엇을 먼저 신뢰할지 짧은 매트릭스
| 신호 | 강점 | 맹점 |
|---|---|---|
| Gateway status JSON | CI diff·아티팩트·요약에 안정적으로 실립니다. | 직후 크래시 직전에는 시차가 날 수 있어 lsof와 세트가 안전합니다. |
| doctor | 프로바이더·디스크 권한류를 이른 단계에서 잡습니다. | 18789 단독 점유를 증명하지는 않습니다. |
lsof 지문 |
Mac에서 리스너 충돌에 대해 사실상 권위 있습니다. | 로그에 민감 정보가 섞이지 않게 발췌 길이를 제한하세요. |
전제 체크리스트
운영에 승격할 러너 이미지에서 위에서 아래로 맞춥니다.
- Node는
launchdplist의ProgramArguments와 같은 계열의 절대 경로로 고정하고,node -v를 로그에 남깁니다. 대화형 셸 전용nvm경로는 기준으로 삼지 않습니다. - OpenClaw CLI는 전역 핀;
command -v openclaw출력을 plist 초안 옆에 붙여 둡니다. - OPENCLAW_CONFIG_HOME은 테스트 대상 설정 트리를 가리키고, 시크릿은 마스킹된 CI 변수로만 주입합니다.
- 프리풀 잡을 선행해 두면 이 게이트가 측정하는 것이 “빈 디스크에서의 우연한 타임아웃”이 아니라 상시 부하에 가깝습니다.
튜토리얼: 단계별 게이트 스크립트
의존성 설치 뒤·머지 전에 실행합니다. 웹훅 요약용으로 스트림을 한 파일로 합칩니다.
export CI=true
# `openclaw gateway status --help`에 나온 JSON·무인(headless) 플래그를 추가
export OPENCLAW_GATE_LOG="${OPENCLAW_GATE_LOG:-openclaw-gate.log}"
: > "$OPENCLAW_GATE_LOG"
{
echo "=== node path ==="
command -v node
node -v
echo "=== openclaw path ==="
command -v openclaw
openclaw --version
echo "=== gateway status json ==="
openclaw gateway status --json > gateway-status.json
python3 -m json.tool gateway-status.json | head -n 80
echo "=== doctor ==="
openclaw doctor
echo "=== config validate ==="
openclaw config validate --config "${OPENCLAW_CONFIG_HOME:?}/openclaw.json"
echo "=== lsof 18789 ==="
lsof -nP -iTCP:18789 -sTCP:LISTEN || true
} 2>&1 | tee "$OPENCLAW_GATE_LOG"
plist를 쓰는 영구 게이트웨이에는 위에서 찍은 절대 경로 openclaw를 그대로 ProgramArguments에 옮깁니다. 리슨 주소·토큰을 바꾼 뒤에는 부분 핫 리로드만 믿지 말고, 리스너와 인증 재료가 일관하는지 이 스크립트로 다시 증명하는 편이 공식 운영 흐름에 가깝습니다.
헬스 판정 바(모두 통과해야 녹)
- JSON: 프로세스 상태가 실행 중이고, 빌드/버전 스탬프가 핀한 CLI와 일치합니다.
- HTTP 프로브: 문서화된 헬스 경로에 루프백
curl로 2xx가 나오며, 엣지가 쓸 토큰과 동일한Authorization을 씁니다. - TCP:
lsof에 기대 PID 하나(또는 CI 스모크 전용으로 의도한 다른 포트)만 보입니다.
headless 파라미터와 관측
CI=true와 함께 openclaw gateway status --help에 기재된 JSON·비대화형 옵션을 켜면 브라우저나 TTY 마법사 없이 기계 가독 출력만 남길 수 있습니다. 자동화에서 pseudo-TTY를 억지로 켜기보다, 표준출력·표준에러를 tee로 openclaw-gate.log에 합치고 그 파일을 파이프라인 아티팩트로 올리세요.
HowTo / FAQPage 구조화 데이터 제안
이 글의 application/ld+json에는 BlogPosting·Article·BreadcrumbList·HowTo(step 순서)·FAQPage가 들어 있습니다. 보강 시 HowToStep에 url 앵커를 추가하고 FAQ 문항을 실제 티켓 제목에 맞추면 됩니다.
흔한 시그니처와 첫 대응
| 표면 증상 | 가능 원인 | 첫 조치 |
|---|---|---|
18789에서 EADDRINUSE |
남은 게이트웨이·중복 launchd 라벨. | lsof의 PID를 중지하거나 CI 스모크 전용 포트로 분리. |
JSON은 정상인데 curl 실패 |
바인드 인터페이스 불일치·토큰 불일치. | openclaw.json 리슨 스탠자와 호스트·Authorization을 diff. |
launchd에서 command not found: openclaw |
최소 PATH에 전역 npm bin 없음. | plist에 절대 경로 또는 PATH 접두 export. |
401 / invalid token |
CI 시크릿만 주입되고 plist 환경은 비어 있음. | 운영 EnvironmentVariables 블록을 잡 로그와 원자적으로 맞춘 뒤 데몬 재시작. |
FAQ
PR 잡에 데몬까지 설치해야 하나요? CLI 게이트만 쓰고 launchd는 장기 호스트에 두면 18789 충돌을 줄입니다.
실행 순서는? JSON status로 프로세스를 고정한 뒤 doctor·validate·lsof 순이 읽기 쉽습니다.
아티팩트 보관? 사후 분석용으로 14일 이상과 tarball 해시를 권장합니다.