HOWTO · Batch

배치 스크립트의 오류 처리

이 자습서에서는 Batch Script의 오류 처리를 살펴봅니다.

이 페이지의 내용

Windows .bat 또는 .cmd 파일에서 오류를 처리하려면 명령의 종료 코드를 즉시 확인하고, 문제가 있으면 알리거나 성공하면 계속 진행하도록 분기하세요. Batch 명령은 관례적으로 성공 시 0, 실패 시 0이 아닌 코드를 반환하지만, 특정 0이 아닌 코드는 해당 명령의 구체적인 상태를 나타낼 수 있습니다. %ERRORLEVEL%은 현재 상태를 보여 주고, IF ERRORLEVEL은 상태가 지정한 값 이상인지 확인합니다.

Batch 오류 수준이 작동하는 방식

명령은 실행을 마치면 종료 코드를 반환합니다. 관례적으로 0은 성공을 뜻하고, 0이 아닌 값은 명령이 성공적으로 완료되지 않았음을 나타냅니다. 다만 그 값의 정확한 의미는 명령마다 다릅니다. 배치 스크립트는 이 상태를 바탕으로 다음에 수행할 작업을 결정할 수 있습니다.

현재 코드를 읽으려면 %ERRORLEVEL%을 사용하고, 임계값을 확인하려면 IF ERRORLEVEL n을 사용하세요. IF ERRORLEVEL n은 현재 코드가 n과 같을 때만 참인 것이 아니라, n 이상일 때 참입니다. 결과가 중요한 명령을 실행한 직후 상태를 확인하세요. 다른 명령이 그 상태를 바꿀 수 있습니다.

명령의 종료 코드 확인하기

여러 임계값을 확인한다면 큰 값부터 검사하세요. 그렇지 않으면 더 큰 코드도 각각의 낮은 임계값을 만족합니다. 값을 직접 비교하려면 명령 직후 %ERRORLEVEL%을 저장한 다음 저장된 값을 비교하세요.

이 예제는 값에 ready라는 텍스트가 있는지 확인합니다. message를 다른 단어로 바꾸면 실패 분기를 확인할 수 있습니다. 저장된 값은 echo 명령이 상태를 바꾸기 전에 findstr에서 바로 가져옵니다. 제공된 패킷에서는 이 Windows 명령 프롬프트 예제를 실행하지 않았습니다.

@echo off
set "message=ready"
echo(%message%| findstr /c:"ready" >nul
set "command_status=%ERRORLEVEL%"
if "%command_status%"=="0" (
    echo Match found.
) else (
    echo Match not found.
)

괄호로 묶인 블록에서는 %variable% 참조가 블록을 구문 분석할 때 확장됩니다. 상태는 블록에 들어가기 전에 저장되므로 비교에는 저장된 결과가 사용됩니다. 정확한 상태를 처리하려면 저장한 값을 비교하세요. 반면 IF ERRORLEVEL n은 현재 상태가 n 이상인지 확인합니다.

조건부 명령으로 오류 처리하기

앞 명령이 성공한 경우에만 다음 명령을 실행하려면 &&를 사용하고, 실패한 경우에만 실행하려면 ||를 사용하세요. 이 연산자는 짧은 분기에 유용합니다.

some_command && echo Success || echo Failure

처리 과정이 길다면 IF 블록이 더 읽기 쉽습니다. IF ERRORLEVEL 1은 코드가 1 이상인지 확인합니다. 따라서 일반적인 0이 아닌 실패 상태를 다루지만, 각 상태의 의미까지 구분하지는 않습니다. 정확한 상태를 처리하려면 위에서 설명한 것처럼 %ERRORLEVEL%을 즉시 저장하고 저장된 값을 비교하세요.

실패와 성공 예제 만들고 확인하기

이 스크립트는 임의의 이름을 사용해 Windows 임시 디렉터리 아래에 새 데모 디렉터리를 만듭니다. 어떤 경로도 삭제하지 않습니다. 디렉터리 만들기에 실패하거나 예상한 입력 파일이 이미 있으면 설정 상태 코드 2로 종료합니다. type을 실행하기 전에 입력 파일이 없는지 확인하며, 예상한 실패 메시지는 파일이 여전히 없을 때만 출력됩니다. 그런 다음 입력 파일을 만들고 쓰기 작업의 결과를 확인한 뒤 같은 파일을 읽습니다. 제공된 패킷에서는 이 Windows 명령 프롬프트 예제를 실행하지 않았습니다.

이 예제를 실행하세요.

@echo off
set "demo_dir=%TEMP%\batch-error-demo-%RANDOM%-%RANDOM%"
set "demo_file=%demo_dir%\input.txt"
if exist "%demo_dir%" (
    echo Setup failed: the randomized demo directory is already present.
    exit /b 2
)
mkdir "%demo_dir%" >nul 2>&1
if errorlevel 1 (
    echo Setup failed: could not create the fresh demo directory.
    exit /b 2
)
if exist "%demo_file%" (
    echo Setup failed: the demo input is already present.
    exit /b 2
)

type "%demo_file%" >nul 2>&1
set "command_status=%ERRORLEVEL%"
if not "%command_status%"=="0" (
    if not exist "%demo_file%" (
        echo Failure: input.txt was not found.
    ) else (
        echo Failure: input.txt could not be read.
        exit /b 1
    )
) else (
    echo Read input.txt successfully.
)

>"%demo_file%" echo ready
if errorlevel 1 (
    echo Setup failed: could not create input.txt.
    exit /b 2
)
type "%demo_file%" >nul 2>&1
if errorlevel 1 (
    echo Failure: input.txt could not be read.
    exit /b 1
)
echo Success: input.txt contains ready.
exit /b 0

첫 번째 확인은 파일이 없을 때의 예상된 실패를 보여 주고, 뒤이은 읽기는 성공을 보여 줍니다. 읽기에 성공하면 스크립트는 0을 반환하고, 읽기에 실패하면 1, 새 데모 디렉터리나 입력 파일을 준비하지 못하면 2를 반환합니다. 관련 없는 데이터를 지우지 않도록 %TEMP%에 고유한 이름의 디렉터리를 남깁니다. 정리하려면 내용을 확인한 뒤 그 디렉터리만 직접 삭제하세요.

오류를 기록하고 유용한 상태 코드 반환하기

유용한 오류 처리기는 실패한 작업을 식별하고, 필요하면 진단 출력을 보존하며, 호출한 쪽에 0이 아닌 상태 코드를 반환합니다. 표준 출력과 표준 오류를 모두 로그에 추가하려면 >> "%LOGFILE%" 2>&1을 사용한 다음 명령의 상태를 즉시 확인하세요. 리디렉션은 출력을 저장하지만 그 자체로 실패를 처리하지는 않습니다.

예를 들어 적절한 로그 경로를 설정한 뒤 스크립트에서 >> "%LOGFILE%" 2>&1을 사용해 명령을 실행하고, 다음 줄에서 %ERRORLEVEL%을 저장한 후 그 값에 따라 분기할 수 있습니다. 실패하면 작업 이름과 로그 파일을 알려 주는 메시지를 출력하고 exit /b 1을 사용하세요. 성공하면 exit /b 0을 사용합니다. 스크립트 사용자가 쓸 수 있는 로그 경로를 선택하고, 모든 0이 아닌 코드의 원인이 같다고 가정하지 마세요.