Springuptech
← 인사이트 목록으로

윈도우에서 만든 스크립트가 리눅스에서만 이상하게 동작할 때 — 눈에 안 보이는 줄바꿈 문자(CRLF vs LF) 해결법

윈도우에서 작성한 셸 스크립트가 리눅스에서 'bad interpreter' 오류를 내거나 인자가 이상하게 넘어가는 문제의 원인인 CRLF 줄바꿈을 쉽게 설명하고, 확인·해결·예방 방법을 정리했습니다.

노재용작성 5분 읽기

분명히 똑같은 스크립트인데, 윈도우에서 수정하고 리눅스 서버에 올렸더니 갑자기 이상하게 동작한 적이 있나요? 오류 메시지를 봐도 코드는 멀쩡해 보여서 한참을 헤매게 되는 문제입니다.

범인은 대부분 눈에 보이지 않는 줄바꿈 문자입니다. 실무에서 실제로 겪은 사례를 바탕으로 원인과 해결 방법을 정리해 드릴게요.

실제로 겪은 상황

리눅스 서버에서 run.sh라는 스크립트로 Java 프로그램을 실행하고 있었습니다. 스크립트는 단순했습니다.

java -cp classpath -Dprop=value my.app.Main $1 $2

그런데 인자를 하나도 주지 않고 ./run.sh를 실행했는데도, Java 프로그램에서 args.length가 0이 아니라 1로 나왔습니다. args[0]을 출력해 보면 빈 문자열처럼 보였습니다.

그래서 그 글자의 코드값을 하나씩 찍어 봤습니다.

for (char c : args[0].toCharArray()) {
    System.out.println("ASCII: " + (int) c);
}

결과는 ASCII: 13. 13은 캐리지 리턴(CR, \r) 이라는 눈에 보이지 않는 문자였습니다.

원인: 운영체제마다 줄바꿈 문자가 다릅니다

텍스트 파일에서 "여기서 줄이 바뀐다"는 표시도 사실은 문자입니다. 그런데 이 문자가 운영체제마다 다릅니다.

운영체제 줄바꿈 문자 이름
윈도우 \r\n (CR + LF) CRLF
리눅스, macOS \n (LF) LF

타자기 시절에 "줄의 맨 앞으로 돌아가기(CR)"와 "종이를 한 줄 올리기(LF)"가 별개의 동작이었던 흔적입니다.

리눅스는 줄 끝을 \n으로만 판단합니다. 그래서 윈도우 형식(CRLF)으로 저장된 스크립트를 리눅스에서 실행하면, 각 줄 끝에 \r이 하나씩 남아 명령어나 인자의 일부로 취급됩니다. 위 사례에서는 $2 뒤에 붙어 있던 \r이 빈 인자 대신 하나의 인자로 전달된 것이었습니다.

이런 증상이 나타나면 의심하세요

  • /bin/bash^M: bad interpreter: No such file or directory
  • $'\r': command not found
  • 파일 경로나 변수 값 끝에 보이지 않는 문자가 붙어서 "파일을 찾을 수 없다"는 오류
  • 위 사례처럼 프로그램에 넘어가는 인자 개수가 이상함

확인 방법

① cat -A로 보이지 않는 문자 표시하기

cat -A run.sh

줄 끝에 ^M$가 보이면 CRLF입니다. ($는 줄 끝, ^M이 바로 \r입니다.) macOS에서는 cat -v를 쓰세요.

② file 명령으로 확인하기

file run.sh
# run.sh: Bourne-Again shell script, ASCII text executable, with CRLF line terminators

with CRLF line terminators라는 문구가 보이면 확실합니다.

③ 실행 과정을 그대로 보기

bash -x ./run.sh

실제로 실행되는 명령이 한 줄씩 출력되어, 인자 끝에 $'\r' 같은 이상한 값이 붙는지 확인할 수 있습니다.

해결 방법

방법 1. dos2unix 사용 (가장 간단)

dos2unix run.sh

설치되어 있지 않다면 sudo apt install dos2unix(Ubuntu) 또는 sudo yum install dos2unix(CentOS 계열)로 설치합니다.

방법 2. sed로 직접 제거

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

별도 설치 없이 대부분의 리눅스에서 바로 쓸 수 있습니다. (macOS의 sed는 sed -i '' 's/\r$//' run.sh 형식입니다.)

방법 3. 편집기에서 변경

  • VS Code: 화면 오른쪽 아래 상태 표시줄의 CRLF를 클릭해 LF로 바꾸고 저장
  • Notepad++: 편집 → EOL 변환 → Unix(LF)

변환한 뒤 다시 실행하면 args.length가 정상적으로 0이 나옵니다.

다시는 겪지 않도록: 예방 설정

한 번 고쳐도 윈도우에서 다시 저장하면 똑같은 문제가 생깁니다. 팀 단위로는 아래 설정을 해 두는 것이 가장 확실합니다.

① Git에서 줄바꿈 규칙 고정하기 (.gitattributes)

저장소 최상위에 .gitattributes 파일을 만들고 다음 내용을 넣습니다.

* text=auto
*.sh text eol=lf

셸 스크립트는 누가 어떤 운영체제에서 받아도 항상 LF로 저장됩니다. 윈도우 전용 배치 파일(*.bat)이 있다면 *.bat text eol=crlf로 따로 지정하세요.

② 편집기 설정 통일하기 (.editorconfig)

root = true

[*.sh]
end_of_line = lf

대부분의 편집기가 이 파일을 읽어 자동으로 줄바꿈 형식을 맞춰 줍니다.

③ VS Code 기본값 바꾸기

설정에서 Files: Eol을 \n으로 지정하면 새 파일이 LF로 저장됩니다.

정리

  • 윈도우는 CRLF(\r\n), 리눅스는 LF(\n)로 줄을 바꿉니다.
  • 윈도우에서 저장한 스크립트를 리눅스에서 실행하면 \r이 남아 이상한 오류가 납니다.
  • cat -A 또는 file로 확인하고, dos2unix나 sed로 변환합니다.
  • .gitattributes와 .editorconfig로 팀 전체의 규칙을 정해 두면 재발을 막을 수 있습니다.

이런 문제는 원인을 알면 1분이면 고치지만, 모르면 하루를 쓰게 됩니다. 윈도우와 리눅스를 오가며 일하는 분들께 도움이 되길 바랍니다.

LinuxBashGit트러블슈팅
노

노재용

Springuptech 대표 개발자 · 22년 차 소프트웨어 엔지니어

이 글과 관련된 프로젝트가 있으신가요?

아이디어 단계여도 괜찮습니다. 무엇이 가능한지 함께 정리해 드립니다.