증상
한 수집기를 끄려고 스위치 파일을 만들었다. 무관한 재시작 작업까지 같이 멈췄다. 둘은 아무 관계가 없다.
원인
같은 스크립트 안에서 무관한 기능이 같은 exit 경로를 공유하고 있었다.
[ -f .col_off ] && exit 0 # 수집기 스위치
run_collector
run_restart_job # ← 아래에 있어서 같이 꺼진다
★★★ 무관한 두 기능이 같은 exit 경로를 공유하면 하나를 끌 때 둘이 꺼진다.
★★ 그리고 끈 사람은 하나만 껐다고 생각한다
★★★ 의도한 것은 정확히 꺼졌으므로 확인해도 정상으로 보인다. 꺼진 줄 모르는 쪽은 아무 신호도 내지 않는다. "수집기를 껐다"는 기록은 남고 "그것도 껐다"는 기록은 어디에도 없다.
★ 왜 자꾸 생기나
스위치는 대개 if 꺼짐: exit 형태로 파일 맨 앞에 들어간다. 그 아래 코드는 전부 그 스위치에 종속되는데, 스위치를 넣는 사람은 아래에 뭐가 있는지 보지 않는다.
★★ 그리고 기능 추가는 파일 끝에 하게 되므로, 시간이 갈수록 맨 앞 스위치 하나가 점점 더 많은 것을 끈다. 처음 넣었을 때는 실제로 정확했다.
해법
★ 기능 스위치는 exit가 아니라 그 기능 블록만 감싸는 조건으로 쓴다.
[ -f .col_off ] || run_collector
[ -f .restart_off ] || run_restart_job
검증 방법
★★ 스위치를 끌 때 "이 아래에 무엇이 있는가"를 먼저 본다. 그리고 ★★★ 끈 결과는 개별 기능 단위로 확인한다 — 의도한 것이 꺼졌는지가 아니라, 의도하지 않은 것이 여전히 켜져 있는지를 본다. 전자만 보면 언제나 통과한다.
★ 같은 형태가 이 컬렉션에 이미 있다 — 폴백 체인에서 앞단이 continue하면 뒷단이 전부 죽는다. 조기 종료는 자기 아래 전부를 대변한다.