로그 읽는 법
로그는 워커와 세션이 자기가 한 일을 시각과 함께 한 줄씩 적어 둔 파일입니다. 셋이 있고, 무엇이 궁금한지에 따라 여는 파일이 다릅니다.
<루트>/workers/runner.log 디스패치 기록
<루트>/workers/logs/<시각>-<워커>-<해시>.log 세션별 실제 출력
<루트>/workers/cron.log cron 자체의 리다이렉트runner.log - 디스패치 기록
워커가 tick마다 무엇을 했는지 여기 남깁니다. 형식은 <시각> [<워커이름>] <메시지>이고,
메시지는 접두어에 따라 구분됩니다.
| 접두어 | 언제 | 뜻 |
|---|---|---|
DISPATCH | 티켓을 가져가 세션을 띄운 순간 | kind-persona-sid-세션 로그 파일명에 유효 우선순위(prio=)를 같이 적는다 |
DONE | 세션이 정상 종료 | 실제 session_id를 적는다. 세션이 .done rename까지 마치고 죽은 경우도 이 낱말이고, 그때는 꼬리에 (세션은 rc=n로 죽었다)가 붙는다 |
FAIL | 세션이 오류로 끝남 | rc가 0이 아니거나 응답의 is_error |
TIMEOUT | TICKET_MAXRUN 초과로 강제종료 | rc가 143/137이고 경과가 상한을 넘었다 |
KILLED | 상한 전에 밖에서 신호로 끊김 | rc는 같은 143/137인데 경과가 상한 미만이다. 강제 할당 해제가 만드는 줄이다 |
STALL | 엔진이 최초 프롬프트를 못 받음 | TICKET_FEED_TIMEOUT 초과 |
NOTE | 멈추지 않는 알림 | 세션키 정정(실제 session_id가 사전 발급값과 다를 때), 엔진 쿨다운 개시, 토큰이 교체되어 쿨다운 해제 |
SKIP | 이번 tick을 건너뜀 | 같은 워커가 앞 세션을 쥐고 있을 때, 다른 워커가 선정 중일 때, 페르소나나 엔진 상한에 걸렸을 때, 엔진 쿨다운이 남았을 때, claude 헤드리스 후보에 인증 토큰이 없을 때(SKIP AUTH 대기 ...는 최초 1회만 남긴다) |
WARN | 멈추지 않는 이상 상황 | 스테일 락 회수-컨텍스트 경로 없음-페르소나 프로필 없음 등 |
ERROR | 디스패치 준비 단계에서 실패 | 네 지점 중 하나 - select 실패-assign 실패-작업 디렉터리(TICKET_CWD) 없음-mkfifo 실패 |
REAP / REAP-FAIL | 죽은 세션이 쥐고 있던 티켓을 회수(또는 회수 실패) | 매 tick 맨 앞, 그리고 세션이 실패로 끝난 자리. 꼬리에 그때까지 센 attempts가 붙고 예산을 넘겨 그 티켓을 대기시킨 회차에만 백오프 600초(누적 n회째)가 더 붙는다 |
ASK / ASK-FAIL | 답변 요청으로 전환(또는 잠금 실패) | reap이 주워 온 회차나 요청 오류로 죽은 회차가 3회째일 때, 또는 세션이 ## 블록을 남기고 멈췄으면 횟수와 무관하게 즉시. 본문에 ## 질문 n이 붙는다. 이어받기 상한으로 잠기는 경우만 이 줄이 안 남는다(아래) |
SUSPECT | 손 클레임 세션이 유휴로 의심됨(보고만) | 자동 회수하지 않는다 |
UNASSIGN / UNASSIGN-FORCE / UNASSIGN-DENY | 할당 해제 성공, 산 세션을 끊고 해제, 산 세션이라 거부 | unassign 명령. 가운데는 --force가 만든다 |
"아무 일도 안 일어나는 것 같다"의 첫 확인 자리가 여기입니다. DISPATCH가 안 남았다면 디스패치
자체가 안 된 것이고(선정 실패, 인증 대기 등), DISPATCH 뒤에 DONE도 FAIL도 없다면 세션이
아직 실행 중입니다.
한 가지 경우는 이 파일에 아무 줄도 안 남깁니다. 이어받기를 세 번 넘긴 티켓은 워커가 가져가는 순간
다시 반납되고 답변 대기로 잠기는데, 그 판정이 claim 명령 안쪽에서 이루어지기 때문에 ASK도
SKIP도 안 남습니다. 티켓 쪽에는 흔적이 남습니다. 본문에 ## 질문 n이 붙고 보드 카드에
답변 대기 배지가 뜹니다. 그 티켓에 관한 줄이 로그에 없는데 티켓이 안 나간다면 그 배지부터
보세요(티켓이 지나는 상태).
logs/<시각>-<워커>-<해시>.log - 세션별 실제 출력
runner.log가 "언제 어떤 티켓을 가져갔나"라면 이 파일은 "그 세션 안에서 무슨 일이
있었나"입니다. 엔진의 표준에러와 최종 표준출력이 여기 쌓입니다. 기본 엔진(claude -p,
스트리밍 입력)에서는 JSONL 한 줄이 곧 한 이벤트고, 마지막 "type":"result" 줄이 그 세션의
최종 판정입니다(FAIL/DONE 판정의 근거).
FAIL이나 TIMEOUT이 runner.log에 남았을 때 왜 실패했는지는 이 파일에서만 보입니다.
runner.log는 판정 결과만 적고, 세션이 실제로 무엇을 읽고 무엇을 시도하다 막혔는지는 여기
담깁니다.
세션이 실행되는 동안에는 대개 비어 있습니다. 워커가 엔진 출력을 따로 모아 두었다가 세션이 끝난 뒤 한 번에 기록하기 때문입니다. 진행중인 세션을 실시간으로 보시려면 티켓 상세의 세션 스트림을 여세요. 그 화면이 읽는 파일은 트랜스크립트입니다. Claude Code가 자기 세션에서 주고받은 말과 도구 호출을 순서대로 적어 두는 기록 파일이며 여기서 설명한 세션 로그와는 별개입니다(화면에서 보는 것 §세션 스트림).
cron.log - 워커 스크립트 자체의 출력
crontab 줄이 리다이렉트하는 대상입니다(>> .../cron.log 2>&1). 여기 쌓이는 것은 워커 셸
스크립트 자체의 표준출력과 표준에러입니다. 세션의 출력은 여기로 오지 않습니다. 정상 동작
중에는 대개 비어 있습니다. tick.sh가 하는 일은 전부 runner.log에 따로 적으니까요. 이 파일에
뭔가 있다면 bash 자체가 실행되지 못했거나(권한, 셔뱅 오류) tick.sh가 시작하기도 전에 죽은
것입니다.
예외가 하나 있습니다. 큐 판정이 표준에러로 내는 WARN 구 레이아웃에 티켓 n건이 남아 있다도
여기로 옵니다. runner.log에서는 아무리 찾아도 안 나오니, 티켓이 보드에서 사라졌을 때는 이
파일도 같이 보세요(트러블슈팅 §티켓이 보드에 안 보인다).
증상별 확인 순서
- 아무 일도 안 일어난 것 같다 ->
runner.log부터 보세요.DISPATCH가 있는지, 있다면 그 뒤에DONE/FAIL/TIMEOUT이 붙었는지 봅니다. runner.log조차 갱신되지 않는다 ->cron.log를 보세요. 워커 자체가 안 뜬 것입니다 (마운트 문제는 트러블슈팅 §워커가 아예 안 뜬다 참고).FAIL/TIMEOUT은 남았는데 이유를 알아야 한다 -> 그 줄 꼬리의로그 <파일명>으로logs/의 세션별 로그를 여세요. 같은 파일명이 그 티켓의DISPATCH줄에도log=로 적혀 있습니다.
다음은 사용 통계와 끄는 법입니다.