Skip to content

fix(infra): 헬스 감시가 정상인데 exit 1 로 끝나던 문제 + ops 자가 테스트를 CI 에 - #261

Merged
i3months merged 1 commit into
devfrom
fix/health-check-exit-code
Sep 28, 2026
Merged

i3months merged 1 commit into
devfrom
fix/health-check-exit-code

Conversation

@i3months

Copy link
Copy Markdown
Member

배포 후 확인하다 나왔다

#260 을 배포하고 cron 과 같은 최소 환경으로 실행해 봤다:

$ env -i HOME=/home/stackup PATH=/usr/bin:/bin /…/health-check.sh
  exit=1
  상태파일: UP

판정은 맞는데 종료 코드가 1이다. 원인:

[ -n "$previous" ] && ops_notify ok "헬스 복구 (이전: $previous)" "$detail"

첫 실행에는 previous 가 비어 있어 && 가 단락되고, 그 마지막 상태가 그대로 스크립트
종료 코드
가 된다.

감시 도구가 정상 상태에서 실패 코드를 내면 "이 cron 은 원래 그래" 가 되고, 진짜 실패도
같이 무시된다.
if 문으로 바꾸고 끝에 명시적 exit 0 을 둔다.

자가 테스트를 스크래치패드에서 레포로

이 스크립트들을 만들면서 실제로 두 번 깨졌고 둘 다 조용한 실패였다:

# 증상 겉보기
1 임베디드 파이썬 따옴표 이스케이프 파손 → 판정이 빈 값 감시가 그냥 통과
2 위의 && 단락 → 정상인데 exit 1 상태파일은 맞게 찍힘

셸은 컴파일러도 타입체커도 없고, 이 둘은 한 번 돌려봐서는 눈에 안 띈다. 그래서 검증을
infra/ops/selftest.sh 로 옮겼다. 로컬 수신기로만 보낸다 — 팀 채널로 아무것도 나가지 않는다.

[notify.sh]
  ok   JSON 이 깨지지 않는다              (따옴표·작은따옴표·백슬래시·줄바꿈)
  ok   웹훅 없으면 무발송
  ok   죽은 엔드포인트가 호출자를 죽이지 않는다
[health-check.sh]
  ok   첫 실행 정상: exit 0 / 무발송
  ok   정상 반복: exit 0 / 무발송
  ok   집계 UP·backup DOWN 포착: exit 0 / 1건
  ok   같은 이상 반복: 발송 늘지 않음
  ok   복구: exit 0 / 2건
  ok   도달 불가: exit 0 / UNREACHABLE 로 기록
통과 14, 실패 0

모든 케이스에서 종료 코드를 함께 확인한다 — 이번에 놓친 게 정확히 그거다.

CI 잡 추가

Infra (ops 스크립트): bash -n · shellcheck -S warning · selftest.

로컬에서 도커로 shellcheck 를 돌려 clean 을 확인했고 YAML 도 파싱 검증했다
(jobs: frontend, backend, ai, realtime, infra). #259 에서 CI 와 다른 명령
(npx tsc --noEmit vs tsc -b)으로 확인해 타입 에러를 놓친 뒤의 습관이다.

현재 서버 상태

헬스 감시 cron 은 이미 등록해 뒀다(허락받은 대로, 5분 주기). 기존 백업 cron 은 보존했다:

0 4 * * *   …/infra/backup/backup.sh  >> …/backup.log 2>&1
*/5 * * * * …/infra/ops/health-check.sh >> …/health.log 2>&1

이 PR 이 머지·배포되면 그 cron 이 고쳐진 스크립트를 집는다. 그전까지는 정상일 때
exit 1 이 찍히지만 판정·알림 동작 자체는 정상이다(상태파일·발송 모두 맞게 동작).

#260 을 배포하고 cron 환경(env -i)으로 실행해 보니 판정은 UP 인데 종료 코드가
1 이었다.

  [ -n "$previous" ] && ops_notify ok ...

첫 실행에는 previous 가 비어 있어 && 가 단락되고, 그 마지막 상태가 그대로
스크립트 종료 코드가 된다. 감시 도구가 정상 상태에서 실패 코드를 내면 "이
cron 은 원래 그래" 가 되고, 진짜 실패도 같이 무시된다. if 문으로 바꾸고 끝에
명시적 exit 0 을 둔다.

## 자가 테스트를 레포로

이 스크립트들을 만들면서 실제로 두 번 깨졌고 **둘 다 조용한 실패**였다:

  1. 임베디드 파이썬 따옴표 이스케이프가 깨져 판정이 빈 값 → 감시가 그냥 통과
  2. 위의 exit 1 → cron 이 정상을 실패로 보고

셸은 컴파일러도 타입체커도 없고, 이 둘은 돌려봐도 눈에 안 띈다. 그래서 검증을
스크래치패드에 두지 않고 infra/ops/selftest.sh 로 옮겼다. 14개 케이스를 로컬
수신기로만 확인한다 — **팀 채널로 아무것도 보내지 않는다.**

  notify.sh       따옴표·백슬래시·줄바꿈 → JSON 무손상 / 웹훅 없으면 무발송 /
                  죽은 엔드포인트가 호출자를 죽이지 않음
  health-check.sh 첫 실행 정상(exit 0, 무발송) / 정상 반복(무발송) /
                  집계 UP 인데 backup DOWN 포착 / 같은 이상 반복 무발송 /
                  복구 알림 / 도달 불가 → UNREACHABLE
                  ※ 모든 케이스에서 exit 0 을 함께 확인한다

## CI

`Infra (ops 스크립트)` 잡 추가: bash -n · shellcheck -S warning · selftest.
로컬에서 도커로 shellcheck 를 돌려 clean 을 확인했고, YAML 도 파싱 검증했다
(#259 에서 CI 와 다른 명령으로 확인해 타입 에러를 놓친 뒤의 습관).
@i3months
i3months merged commit 2e95785 into dev Sep 28, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant