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 작업은 등록 직후 로그로 실제 실행 여부를 한 번 확인하는 습관이 싸게 먹힌다.
댓글 없음:
댓글 쓰기