어떤 스크립트는 OS에 따라서 실행성이 변경되기도 합니다. 이것은 CRLF/LF 개행 문자 차이로 인한 것입니다. Gradle 에서 다음과 같은 오류가 발생했다면 개행 문자의 차이로 인한 것일 수도 있습니다. 그런 차이를 우리는 평소에는 인지하지 못하고 있을 수 있습니다. 개행 문자는 화면에 표시되지 않기 때문입니다.
자세한 내용은 아래에 작성합니다.
이번에 진행하는 프로젝트는 개발자의 개발 환경이나, 배포가 진행될 서버 이외의 다양한 환경에서 작동할 필요가 있었습니다. 개발 PC에서 Docker-compose 환경을 통해 Spring Boot + PostgreSQL + Redis 를 포함해 Docker 실행이 정상적으로 진행되는 것을 확인하고, 테스트 삼아 개발 PC 이외에도 게이밍 PC, 개인 보유 리눅스 서버 등에서 테스트 배포를 시작했습니다. 문제는 게이밍 PC에서 테스트할 때 발생했습니다.
개발 PC에서 정상적으로 작동하던 docker-compose build 에서 문제가 발생했습니다. 커맨드 자체는 도커를 실행한 것이나, 오류 메시지를 확인하면 도커에서 실행한 Gradle Wrapper 에서 오류가 발생한 것입니다.
Gradle bin/sh: ./gradlew: /bin/sh^M: bad interpreter
gradlew 파일은 Spring Initializr가 자동으로 생성해준 것입니다.
원인은 OS별 개행 문자 차이에 의한 것입니다. Windows OS에서는 CRLF 형식의 개행 문자를 사용하고, Unix 기반 OS(리눅스, MacOS) 에서는 LF를 개행 문자로 사용합니다.
OS 별로 사용하는 개행 문자가 다르다보니 소스코드를 관리하는 Git 역시 이를 관리하는 정책이 복잡한데, 기본적으로는 OS에 맞춰서 자동으로 관리가 됩니다. 즉, 사용자가 Windows OS라면 CRLF 로 코드를 불러오고, Unix 기반의 OS에서는 LF 로 불러오게 됩니다. 사용자는 원한다면 위와 같은 방식에서 다른 정책으로 변경이 가능하지만, 기본값은 'OS에 맞춰서 자동 변환' 이고 제 git 설정 또한 기본값으로 설정 되어있습니다.
제 개발용 PC는 Mac을 사용하고 있으므로 최초에는 LF 상태로 gradlew 가 작성되었을 것입니다. OS에 맞는 스크립트이므로 문제 없이 작동합니다.
제 Windows PC에서 원격 저장소를 git clone 했을 때, LF의 소스코드들은 CRLF 로 변환되었을 것입니다. 따라서 스크립트들은 문제 없이 작동합니다.
Dockerfile 에 맞게 docker-compose build를 실행했을 때, ./gradlew 은 Docker 컨테이너 내부에서 실행됩니다. 사용한 image는 amazoncorretto:17 이고, 이 이미지는 linux 베이스의 이미지입니다.
즉, Windows 에서 정상적으로 실행되던 gradlew 파일을 그대로 docker 내부에서 사용하면 스크립트는 정상적으로 실행되지 않습니다.
사용하고 있는 IDE인 IntelliJ에는 개행문자를 변경할 수 있는 기능이 있습니다. 이를 활용해 LF 로 전환을 해주자 문제 없이 작동했습니다.
서버 상에서 문제를 해결해야 할 경우에는 다음과 같은 방식을 사용합니다.
vi gradlew
:set fileformat=unix
!wq
gradlew 빌드가 정상적으로 실행되는 것을 확인할 수 있습니다.
Stackoverflow : /bin/sh^M: bad interpreter: No such file or directory