2026년 11월 13일 금요일

Windows 에서 올린 셸 스크립트가 cron 에서만 조용히 실패할 때 — CRLF

Windows 에서 작성해 서버에 올린 백업 스크립트가 cron 에서 한 번도 돌지 않았다. 손으로 실행하면 될 때도 있어서 원인을 찾는 데 오래 걸렸다. 범인은 줄 끝의 CRLF 였다.

증상

  • crontab 에 등록한 .sh 가 정해진 시각에 아무 결과도 남기지 않는다.
  • cron 메일이나 로그를 보면 not found 한 줄뿐이다. 파일은 분명히 있고 실행 권한도 있다.
  • bash script.sh 로 직접 실행하면 일부는 돌아가서, 스크립트 자체는 멀쩡하다고 착각하게 된다.

원인

Windows 편집기는 줄 끝을 CRLF(\r\n)로 저장한다. 그러면 첫 줄이 이렇게 된다.

#!/bin/bash\r

커널은 /bin/bash\r 이라는 이름의 인터프리터를 찾는데, 그런 파일은 없다. 그래서 "스크립트가 없다"가 아니라 "인터프리터가 없다"는 뜻의 not found 가 나온다. 메시지만 보면 스크립트 경로가 틀린 것처럼 읽혀서 헷갈린다.

bash script.sh 로 실행하면 shebang 을 쓰지 않으니 시작은 되지만, 각 줄 끝에 \r 이 붙은 채로 해석되어 변수 값이나 경로 끝에 보이지 않는 문자가 섞인다. Python 스크립트도 shebang 으로 실행하면 같은 이유로 실패한다.

확인

file script.sh          # "with CRLF line terminators" 가 보이면 당첨
head -1 script.sh | od -c | head -2   # \r \n 확인

해결

당장은 서버에서 변환한다.

sed -i 's/\r$//' script.sh

근본적으로는 저장소에서 줄 끝을 고정한다. .gitattributes 한 줄이면 Windows 에서 체크아웃해도 LF 로 유지된다.

* text=auto eol=lf

이미 CRLF 로 커밋된 파일이 있다면 설정을 넣은 뒤 git add --renormalize . 로 한 번 정리한다.

정리

cron 은 실패를 눈앞에 보여 주지 않는다. Windows 에서 만든 스크립트를 서버에 올린다면 .gitattributes 로 LF 를 강제해 두고, 새 cron 작업은 등록 직후 로그로 실제 실행 여부를 한 번 확인하는 습관이 싸게 먹힌다.

댓글 없음:

댓글 쓰기

반도체 주식을 보기 전에 그려 두는 지도 — 설계, 파운드리, 메모리, 장비, 소재, 후공정

"반도체주"라고 한 묶음으로 부르지만, 그 안의 회사들은 하는 일도 돈 버는 방식도 전혀 다르다. 같은 뉴스에 어떤 회사는 오르고 어떤 회사는 내리는 이유가 여기에 있다. 종목을 들여다보기 전에 머릿속에 그려 두면 좋은 지도를 정리한...