Claude -p의 정기 실행이 실패해도 종료 코드는 0입니다. 보고서 끝 상태 행에서 이상을 감지하는 방법
요약
Claude Code를 스케줄러에서 실행할 때 종료 코드(Exit Code)만으로는 작업의 성공/실패 여부를 판단하기 어렵습니다. AI 에이전트는 실패해도 정상적으로 0 코드를 반환하며, 따라서 보고서 마지막에 특정 형식(`ROUTINE-STATUS: ALERT`)을 강제하여 상태를 명시하는 것이 가장 확실한 감지 방법입니다.
핵심 포인트
- AI 에이전트의 종료 코드(Exit Code)는 프로세스 다운 여부만 판단 가능합니다.
- 실패 시에도 0 코드가 반환되므로, 로그 분석에 의존해서는 안 됩니다.
- 보고서 마지막 줄에 `ROUTINE-STATUS: ALERT`와 같은 고정 형식을 강제하는 것이 효과적입니다.
- 파워셸 스크립트에서 정규 표현식(`^...$`)을 사용하여 상태 행의 정확성을 검증해야 합니다.
저는 Claude Code를 작업 스케줄러(Task Scheduler)에서 claude -p로 매일 실행하고 있습니다. 런처(실행용 PowerShell 스크립트)에는 '종료 코드가 0이 아니면 알림을 발생시킨다'는 감시 장치를 설치해 두었습니다.
어느 날 아침, 루틴 작업 중 X 예약 게시가 실패했음에도 불구하고 알림이 울리지 않았습니다. 종료 코드는 0이었기 때문입니다. 이 글은 그때 적용한 대책에 대한 메모입니다.
- 창을 열지 않는 설정으로 Chrome 작업을 시켰기 때문에 날짜 선택기가 그려지지 않아 예약 날짜를 입력할 수 없었습니다.
- Claude는 절차를 멈추고 보고서에 '예약 실패'라고 작성한 후 종료했습니다.
- 종료 코드는 0이었습니다. 런처의 감시 장치는 아무것도 감지하지 못했습니다.
- 깨달은 것은 열려 있는 브라우저 탭을 봤을 때였습니다.
곰곰이 생각해보니 당연했습니다. claude -p 프로세스로서의 역할은 '지시를 받아 답변 작성을 완료하는 것'입니다. 실패했다는 것을 답변에 적었을 시점부터 프로세스는 정상 종료됩니다. 0이 아니게 되는 경우는 프로세스 자체가 다운되거나 강제 종료되었을 때뿐입니다.
| 알고 싶은 것 | 종료 코드로 파악 가능한가 |
|---|---|
| 에이전트가 끝까지 작동했는지 | 알 수 있다 |
| 요청한 절차가 성공했는지 | 알 수 없다 (실패해도 0) |
사람이 작성하는 스크립트라면 실패 지점에서 exit 1을 하면 되지만, 에이전트는 '실패했습니다'라고 문장으로 적고 그대로 정상 종료합니다.
또 다른 패턴으로는 본체 답변 이후에 백그라운드에서 실행되는 처리의 대기 시간 상한에 걸린 경우도 결과물 파일 없이 0으로 끝났습니다.
정상적인 보고서에도 이러한 단어들이 보통 나옵니다.
・링크 끊김: 이상 없음
・이전 오류는 재발하지 않음
이를 감지하면 매일 오보 알림이 울리고, 결국 아무도 알림을 보지 않게 됩니다. 작성 방식을 강제하기보다, 판단에 사용할 장소를 한 곳으로 정하고, 그곳에서만 일정한 형태로 작성하도록 하는 것이 더 확실합니다.
스킬(절차서)의 보고 부분에 다음 내용을 추가했습니다.
보고서 마지막 줄에 다음 중 하나를 단 1줄만 작성:
ROUTINE-STATUS: OK … 모든 절차가 성공했거나 예정대로 건너뛴 경우
ROUTINE-STATUS: ALERT … 실패한 절차가 하나라도 있는 경우
정한 포인트는 세 가지입니다.
- 일반적인 문장에 나오지 않는 형태로 만듭니다 (영문 대문자 + 콜론) -
- 선택지를 두 개로 제한합니다. '확인 필요'와 같은 중간 지점을 만들면 AI가 그곳으로 빠집니다 -
- 예정대로 건너뛴 것은 OK에 포함시킵니다. 새로운 것이 없어 아무것도 하지 않은 날마다 ALERT가 나오는 것을 방지합니다.
종료 코드 판별은 유지하되, 0일 때만 상태 행을 확인하도록 했습니다.
$output = & claude -p "/my-routine" 2>&1
$exitCode = $LASTEXITCODE
if ($exitCode -ne 0) {
...
처음에는 '출력의 마지막 1줄'만 보았지만, 검토를 거쳐 수정했습니다.
- 상태 행 뒤에 빈 줄이나 마무리 문구가 붙는 경우가 있습니다.
- 보고 도중에 '상태 행은 ROUTINE-STATUS: ALERT가 됩니다'처럼 설명으로 같은 문자열을 작성하는 경우가 있습니다.
그래서 '줄의 시작이 ROUTINE-STATUS:인 행 중 마지막 것'을 가져와, ^과 $를 사용해 ALERT가 정확한지 확인하고 있습니다. Send-Alert는 환경에 맞게 대체해 주세요. 알림 본문은 로그 위치와 간단한 문구만 남겼습니다.
빈틈은 '상태 행을 작성하는 것을 잊었을 때 감지할 수 없다'는 것입니다. 지금은 대응된 루틴이 일부이므로 '상태 행이 없으면 아무것도 하지 않는다'로 했지만, 전부 대응하면 상태 행 자체가 없는 것을 ALERT로 할 예정입니다.
또 하나, 매일 아침 보고처럼 성공하면 반드시 파일이 생성되는 루틴에서는 '오늘 날짜의 파일이 있는지'도 확인합니다. 대기 시간 상한으로 멈춘 경우는 보고서를 작성하기 전에 멈추므로 상태 행에는 나타나지 않습니다.
결과적으로 감시 장치는 3단계가 되었습니다.
| 확인할 항목 | 포착 가능한 실패 |
|---|---|
| 종료 코드가 0이 아닐 경우 | 에이전트 자체가 끝까지 작동하지 않았음 |
| ... | |
| "실패하면 AI 자체에 알리게 하면 된다"는 안도 있었지만 채택하지 않았습니다. 종료 코드가 0이 아닌 실패의 경우에는 AI가 알림을 보낼 수 없으므로, 결국 런처(launcher) 역시 감시해야 합니다. 알림 출처가 두 곳이 되면, 울리지 않았을 때 어느 쪽을 놓쳤는지 추적하기 어렵습니다. 에이전트는 상태만 기록하고, 알리는 것은 런처만으로 분리했습니다. |
claude -p
의 종료 코드는 '끝까지 작동했는지'만 알려줍니다. 절차상의 실패는 0을 반환하므로 - 출력 전체에 대한 grep은 오탐지합니다. 기계가 읽는 것은 최종 줄 근처의 정형화된 한 줄뿐입니다.
- 예정대로 건너뛰기는 OK로 간주합니다
- 결과물 파일의 유무도 함께 확인합니다
- 알림 출처를 런처 하나로 통일합니다
사람이 읽는 보고서와 기계가 읽는 한 줄을, 같은 응답 안에서 분리해 두는 것이 핵심이었습니다.
이 글은 Claude Code에 작성하게 한 일기 블로그 '고래와 AI와'의 글을 바탕으로, 운영하는 제가(고래) 다시 쓴 것입니다.
원문: https://kujiragames.com/2026/10/routine-status-last-line/
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기