리눅스 환경에서 Bash 스크립트를 통해 Java 프로그램을 실행할 때, 인자를 전달하지 않았는데도 Java의 args.length가 1로 나오는 이상한 상황을 겪은 적 있나요? 저도 최근에 이 문제를 마주쳤고, 원인을 파악하고 해결한 과정을 공유하려고 합니다. 특히, Windows와 Linux 간 줄 끝 문자(CRLF vs LF) 차이에서 비롯된 문제였어요. 이 글에서는 문제 원인과 해결 방법을 간단히 정리해드릴게요!
문제 상황
run.sh라는 Bash 스크립트를 통해 Java 프로그램을 실행했어요. 스크립트는 다음과 같이 작성되어 있었습니다:
java -cp classpath -Dprop=value ki.method $1 $2
이 스크립트를 인자 없이 실행(./run.sh)했는데, Java 코드에서 args.length가 0이 아니라 1로 나왔어요. 더 놀라운 건 args[0]을 출력해보니 빈 문자열처럼 보였지만, args[0].charAt(0)의 ASCII 값을 찍어보니 13이 나왔습니다. 이건 캐리지 리턴(CR, \r) 문자였죠!
원인: CRLF 줄 끝 문자
문제의 원인은 run.sh 파일이 Windows 환경에서 작성되었거나, Windows 스타일 줄 끝 문자(CRLF, \r\n)를 포함하고 있었기 때문이에요. 리눅스에서는 줄 끝 문자로 LF (\n)만 사용하는데, CRLF가 포함된 스크립트를 리눅스에서 실행하면 \r (ASCII 13)이 인자나 문자열에 섞일 수 있어요.
제 경우, run.sh 파일이 CRLF로 저장되어 있어서 Bash가 이를 처리하는 과정에서 \r이 args[0]로 전달된 거였어요. 그래서 args.length가 1이 되고, args[0]이 눈에 보이지 않는 \r 문자로 채워진 거죠.
확인 방법
줄 끝 문자 확인: 스크립트 파일에 \r이 포함되어 있는지 확인하려면 다음 명령어를 사용하세요:
cat -v run.sh
줄 끝에 ^M이 보인다면 CRLF가 포함된 겁니다.
인자 디버깅: 스크립트 실행 시 어떤 인자가 전달되는지 확인하려면:
bash -x ./run.sh
이 명령어는 스크립트 실행 과정을 보여주며, java ki.inter 뒤에 \r 같은 이상한 인자가 붙는지 확인할 수 있어요.
Java에서 args 확인: Java 코드에서 args[0]의 내용을 자세히 확인하려면:
if (args.length > 0) {
System.out.println("args[0]: '" + args[0] + "'");
System.out.println("args[0] length: " + args[0].length());
for (char c : args[0].toCharArray()) {
System.out.println("Char: " + c + ", ASCII: " + (int) c);
}
} else {
System.out.println("No args provided");
}
제 경우, ASCII: 13이 출력되며 \r이 문제임을 알게 됐어요.
해결 방법
문제를 해결하려면 run.sh 파일을 리눅스 스타일 줄 끝(LF)으로 변환하면 됩니다. 다음 두 가지 방법 중 하나를 사용하세요:
dos2unix 명령어:
dos2unix run.sh
이 명령어는 CRLF를 LF로 변환해줍니다.
sed로 직접 제거:
sed -i 's/\r$//' run.sh
파일 끝의 \r을 제거해요.
변환 후 스크립트를 다시 실행하면 args.length가 0으로 정상 출력되고, \r이 인자로 전달되지 않아요.
추가 팁
Git 설정 확인: Git을 사용할 때 Windows와 Linux 간 파일을 공유하면 CRLF가 섞일 수 있어요. .gitattributes 파일에 text eol=lf를 추가해 모든 파일이 LF로 저장되도록 설정하세요.
편집기 설정: VS Code나 다른 편집기에서 파일을 저장할 때 줄 끝을 LF로 설정하세요. 예: VS Code에서 Files: Eol을 \n으로 설정.
인자 처리 주의: Bash 스크립트에서 $1, $2를 사용할 때 ${1:-""} 같은 default 값 설정이 있다면, 의도치 않은 빈 문자열이나 제어 문자가 전달될 수 있으니 주의하세요.
결론
Windows와 Linux 간 줄 끝 문자 차이(CRLF vs LF)는 간단하지만 골치 아픈 문제를 일으킬 수 있어요. 특히 Bash 스크립트로 Java 프로그램을 실행할 때, \r 같은 제어 문자가 인자로 섞이면 디버깅이 까다로워지죠. cat -v, dos2unix, 그리고 Java 디버깅 코드를 활용해 문제를 빠르게 잡아낼 수 있으니, 비슷한 문제로 고민 중이라면 이 방법을 시도해보세요!
혹시 비슷한 경험 있으시면 댓글로 공유 부탁드려요! 😊
'IT > Java' 카테고리의 다른 글
| 스타터 (0) | 2023.12.17 |
|---|---|
| interface 의 구현 (0) | 2013.08.14 |
| 자바의 특징 (0) | 2013.07.17 |
댓글