macOS엔 timeout이 없다 — 프론트 자동화가 127로 멈춘 날
macOS에서 timeout 명령이 종료 코드 127로 실패하는 이유와, 프론트엔드 자동화 스크립트를 gtimeout·Node 타임아웃으로 고친 과정을 정리했어요.
CI에서는 멀쩡히 돌던 스크린샷 자동화 스크립트가 맥북에서만 죽은 적이 있어요. 로그를 열어 보니 에러 메시지도 없이 종료 코드 127 하나만 남아 있었죠. 혹시 비슷한 숫자를 보신 적 없나요?
종료 코드 127이 말해주는 것
127은 "명령을 찾지 못했다"는 뜻이에요. 스크립트 문법이 틀린 게 아니라, 호출한 명령 자체가 그 컴퓨터에 없다는 신호예요.
범인은 timeout이었어요. 직접 확인해 보니 macOS 기본 환경에는 GNU coreutils의 timeout 명령이 들어 있지 않아요. 리눅스 CI에서는 기본 제공이라 잘 돌고, 내 맥에서는 127로 무너지는 구조였던 거예요.
화면 작업인데 왜 셸이 문제였을까
프론트엔드는 컴포넌트만 만지는 것 같지만, 돌려 보니 자동화 스크립트 세 군데에 timeout이 숨어 있었어요.
- dev 서버가 뜨기를 기다렸다가 화면 스크린샷을 찍는 스크립트
- E2E 테스트 전에 빌드가 60초 안에 끝나는지 감시하는 래퍼
- 미리보기 서버를 잠깐 띄웠다 내리는 정리 스크립트
플랜씨(plan-c) 금융계산기 화면의 시안 스크린샷을 자동으로 뽑는 작업도 이 패턴이었어요. 컴포넌트 코드는 한 줄도 안 고쳤는데 자동화만 멈춘 상황, 꽤 억울하죠.
고치는 방법 세 가지
가장 빠른 길은 brew install coreutils 한 줄이에요. 설치하면 gtimeout이라는 이름으로 같은 기능을 쓸 수 있어요. 다만 새 맥을 세팅할 때마다 다시 설치해야 하니, 미래의 내가 또 밟을 함정이긴 해요.
제가 정착한 방법은 셸 대신 Node로 옮기는 쪽이었어요. 프론트 프로젝트에는 이미 Node가 있으니까요. child_process의 execSync에 timeout 옵션을 밀리초 단위로 주면(60초면 60000) 리눅스와 맥에서 똑같이 동작해요. 적용해 봤더니 CI와 로컬의 결과 차이가 사라졌어요.
이미 설치된 도구를 재사용하는 길도 있어요. E2E 러너에 서버 기동 대기와 타임아웃 옵션이 내장된 경우가 많아서, 래퍼 스크립트 자체를 지울 수 있는지 먼저 확인해 보세요. 스크립트가 없어지는 게 제일 깔끔한 해결이더라고요.
- 127 = 명령 없음
- 124 = 시간 초과
- gtimeout은 설치 필요
- Node 타임아웃은 크로스플랫폼
참고로 GNU timeout은 시간 초과로 프로세스를 끊으면 종료 코드 124를 반환해요. 바꿔서 테스트해 보면 127과 124를 구분하는 것만으로도 "명령이 없는 건지, 진짜 느린 건지"를 로그에서 바로 가를 수 있어요.
작은 정리
셸 유틸리티는 OS마다 조금씩 달라요. 화면을 만드는 사람에게도 자동화 스크립트는 결국 제품의 일부라서, 시간 제어처럼 플랫폼을 타는 부분은 이미 갖고 있는 Node 도구체인에 두는 편이 반복을 줄여요. 오늘 스크립트에서 timeout을 발견했다면, 맥에서 한 번 돌려 보고 시작하세요.
관련 글
댓글
아직 댓글이 없어요. 첫 댓글을 남겨주세요.