본문 바로가기

(개인Project)_개발/PLC-PC 연결

[Program][보족] bat 파일 더블클릭했는데 창이 바로 닫힌다 (줄바꿈 문자 문제일 수 있습니다)

반응형

이 글이 나한테 해당되는 얘기인지 먼저 확인해보세요

이런 상황이 하나라도 해당된다면, 이 글이 도움이 될 겁니다.

  • Python으로 만든 bat 파일을 더블클릭했는데 창이 바로 닫히거나 아무 일도 안 일어난다
  • 메모장으로 bat 파일을 열면 내용이 한 줄로 붙어 보인다
  • bat 파일이 cmd에서는 실행되는데 더블클릭하면 안 된다
  • Python 스크립트로 설치/실행 파일을 자동 생성하는데 Windows에서 이상하게 동작한다

PLCLink를 배포할 때 실행 스크립트를 Python으로 자동 생성했습니다.

서버 PC에서 uvicorn과 Vite를 매번 직접 명령어로 치는 건 현장 엔지니어한테 부담입니다.

그래서 start.bat, stop.bat 파일을 배포 패키지에 포함시켜서 더블클릭만 하면 실행되게 만들었습니다.

Python으로 bat 파일을 생성하는 건 간단합니다. open()으로 파일을 쓰면 됩니다.

with open('start.bat', 'w') as f:
    f.write('@echo off\n')
    f.write('cd backend\n')
    f.write('uvicorn main:app --host 0.0.0.0 --port 8765\n')

만들어졌습니다. 현장 PC에서 더블클릭했습니다.

창이 잠깐 떴다가 닫혔습니다. 아무것도 실행되지 않았습니다.


메모장으로 열어봤다

▲ 정상 bat 파일(CRLF)과 깨진 bat 파일(LF만) 메모장 비교. LF만 있으면 줄이 구분되지 않고 한 줄로 붙어 보입니다.

 

bat 파일이 이상한 건지 먼저 확인하려고 메모장으로 열어봤습니다.

내용이 이랬습니다.

@echo offcd backenduvicorn main:app --host 0.0.0.0 --port 8765

줄이 구분되지 않고 전부 붙어있었습니다.

줄바꿈이 없는 상태로 파일이 만들어진 거였어요.

정확하게는 줄바꿈 문자가 없는 게 아니라, Windows가 인식하지 못하는 방식으로 들어가 있었습니다.


LF와 CRLF의 차이

▲ LF와 CRLF의 차이. Windows는 CRLF를 줄바꿈으로 인식하고, LF만 있으면 한 줄로 처리합니다.

 

텍스트 파일에서 줄바꿈은 눈에 보이지 않는 문자로 표시됩니다. 그런데 이 문자가 OS마다 다릅니다.

LF   (Line Feed, \n)        — Unix, macOS, Linux 방식
CRLF (Carriage Return + Line Feed, \r\n)  — Windows 방식

Python 코드에서 \n으로 줄바꿈을 썼는데, Windows bat 파일은 \r\n을 기대합니다.

\n만 있으면 줄이 구분되지 않고 명령어들이 전부 이어붙습니다.

실행할 때 @echo offcd backenduvicorn...이라는 알 수 없는 명령어를 실행하려다가 실패하는 겁니다.

 

Python에서 open()을 텍스트 모드('w')로 쓰면 OS에 따라 줄바꿈을 자동으로 변환해줍니다.

Windows에서 실행하면 \n\r\n으로 바꿔줍니다.

그런데 이 변환이 항상 기대대로 되지는 않습니다.

특히 Python을 WSL(Windows Subsystem for Linux)이나 Git Bash 환경에서 실행하거나, 파일 생성 코드가 Unix 환경을 기준으로 짜여있으면 \n만 들어가는 경우가 생깁니다.

PLCLink 배포 스크립트가 그 케이스였습니다.


해결 방법

▲ 두 가지 해결 방법 비교. open('wb')로 raw bytes 쓰기와 newline='\r\n' 명시.

 

해결 방법은 두 가지입니다.

방법 1 — open('wb')로 raw bytes 작성

content = '@echo off\r\n'
content += 'cd backend\r\n'
content += 'uvicorn main:app --host 0.0.0.0 --port 8765\r\n'

with open('start.bat', 'wb') as f:
    f.write(content.encode('utf-8'))

바이너리 모드('wb')로 열면 Python이 줄바꿈을 건드리지 않습니다.

\r\n을 직접 써준 그대로 파일에 들어갑니다. 가장 확실한 방법입니다.

 

방법 2 — newline 파라미터 명시

with open('start.bat', 'w', newline='\r\n') as f:
    f.write('@echo off\n')
    f.write('cd backend\n')
    f.write('uvicorn main:app --host 0.0.0.0 --port 8765\n')

newline='\r\n'을 지정하면 \n을 쓸 때마다 자동으로 \r\n으로 변환됩니다.

코드 안의 줄바꿈을 \n으로 유지할 수 있어서 가독성이 조금 낫습니다.

PLCLink에서는 방법 1을 썼습니다.

배포 환경이 어디든 줄바꿈이 변환될 여지가 없는 방식이 더 안전하다고 판단했습니다.


확인하는 방법

만들어진 bat 파일의 줄바꿈 문자를 확인하고 싶으면 메모장보다 VS Code나 Notepad++를 쓰는 게 낫습니다.

VS Code라면 우측 하단 상태바에 CRLF 또는 LF가 표시됩니다. LF로 표시되면 Windows bat 파일로 쓰기에 문제가 있는 상태입니다.

# 또는 Git Bash / PowerShell에서 직접 확인
# 파일에 \r 이 있으면 CRLF, 없으면 LF만
cat -A start.bat | head -3
# CRLF면 줄 끝에 ^M$ 표시
# LF만 있으면 $ 만 표시

정리

증상:  Python으로 만든 bat 파일이 Windows에서 실행 안 됨
       메모장으로 열면 줄이 구분 안 되고 한 줄로 붙어 있음
원인:  Python이 LF(\n)만 써서 만든 파일
       Windows bat 파일은 CRLF(\r\n)를 기대함
해결:  open('wb')로 raw bytes 작성 + \r\n 직접 삽입
       또는 open('w', newline='\r\n') 사용

배포 스크립트를 Python으로 자동 생성하는 경우라면 한 번쯤 확인해볼 만한 내용입니다.

코드 자체는 아무 문제가 없어 보여도 파일 하나가 이유로 현장에서 "실행이 안 돼요"가 나오면 찾는 데 시간이 걸립니다.

짧은 내용이지만 PLCLink 배포 테스트 중에 실제로 걸렸던 부분이라 기록해둡니다.

반응형