Trap 을 사용한 오류 처리

ShellBeginner
지금 연습하기

소개

스크립트는 실행 중에 임시 파일을 만들거나 백그라운드 프로세스를 시작하는 경우가 많습니다. 사용자가 Ctrl+C를 눌러 스크립트를 중단하면 이러한 임시 파일이 시스템에 남아 불필요한 파일이 쌓일 수 있습니다.

이를 방지하려면 스크립트가 중단되는 시점을 감지하고 필요한 정리 작업을 수행할 방법이 필요합니다.

Linux 에서는 trap 명령을 사용해 중단 신호와 종료 이벤트를 감지합니다. 신호는 운영 체제가 프로세스와 통신하는 방법 중 하나입니다. 예를 들어 Ctrl+C를 누르면 일반적으로 SIGINT가 전송되어 프로세스에 중지를 요청합니다.

이를 통해 스크립트가 종료되기 전에 스스로 정리할 수 있도록 "종료 시 실행할" 절차를 정의할 수 있습니다.

이 실습에서는 다음 작업을 수행합니다.

  1. 임시 파일을 생성하는 스크립트를 작성합니다.
  2. 스크립트를 중단하고 남은 파일을 확인합니다.
  3. trap 을 구현해 종료 시 임시 파일을 자동으로 삭제합니다.

장시간 실행되는 프로세스 만들기

먼저 장시간 실행되는 작업을 시뮬레이션하는 스크립트를 만듭니다. 이 스크립트는 임시 파일을 만든 다음 무한히 대기합니다.

장시간 실행되는 스크립트는 시스템 관리 작업에서 자주 사용합니다. 로그를 감시하거나, 입력을 기다리거나, 서비스를 주기적으로 확인하거나, 일정 시간 동안 작업을 처리할 수 있습니다. 스크립트가 오래 실행될수록 중단될 때 정리 작업이 더 중요해집니다.

프로젝트 디렉터리에서 long_process.sh를 만들고 엽니다.

cd ~/project
nano long_process.sh

다음 코드를 입력합니다.

#!/bin/bash

## Create a temporary file
touch temp_data.txt
echo "Temporary file 'temp_data.txt' created."

## Fall asleep (Simulate a long job)
echo "Process is running. Press Ctrl+C to stop..."
while true; do
  sleep 1
done

저장하려면 Ctrl+O를 누른 다음 Enter를 누릅니다. 종료하려면 Ctrl+X를 누릅니다.

스크립트에 실행 권한을 추가합니다.

chmod +x long_process.sh

문제: 이 스크립트를 실행한 다음 Ctrl+C로 중단하면 temp_data.txt 파일이 디스크에 남습니다. 이렇게 반복해서 실행하면 불필요한 파일이 쌓여 디스크 공간을 차지할 수 있으므로 좋지 않은 방식입니다.

임시 파일이 대표적인 예이지만, 잠금 파일, 소켓, 마운트 지점 또는 백그라운드 보조 프로세스에서도 같은 문제가 발생할 수 있습니다. 정리 작업의 핵심은 시스템을 예측 가능한 상태로 유지하는 것입니다.

정리 함수 정의하기

정리 작업을 올바르게 처리하려면 모든 정리 로직을 포함하는 별도의 함수를 정의하는 것이 좋습니다.

정리 작업을 별도 함수로 분리하면 스크립트를 체계적으로 관리할 수 있습니다. 또한 여러 위치에 같은 로직을 복사하지 않고, 서로 다른 종료 경로에서 동일한 정리 로직을 재사용할 수 있습니다.

스크립트를 다시 엽니다.

nano long_process.sh

스크립트의 맨 위에 cleanup 함수를 추가합니다.

#!/bin/bash

## Define the cleanup function
cleanup() {
  echo ""
  echo "Cleaning up temporary files..."
  rm -f temp_data.txt
  echo "Cleanup complete."
}

## Create a temporary file
touch temp_data.txt
echo "Temporary file 'temp_data.txt' created."

## Simulate a long-running process
echo "Process is running. Press Ctrl+C to stop..."
while true; do
  sleep 1
done

저장하고 종료합니다.

현재는 함수를 정의했지만, 스크립트에 이 함수를 언제 호출할지 알려주지는 않았습니다.

신호를 감지하도록 Trap 설정하기

이제 trap 명령을 사용해 Bash 에 다음과 같이 지시합니다. "Ctrl+C와 같은 중단 신호를 받으면 cleanup 함수를 실행합니다."

이는 셸 스크립트가 단순히 텍스트 입력에 반응하는 것이 아니라 운영 체제 이벤트에도 반응하는 모습을 잘 보여주는 예입니다. 신호는 시스템이나 사용자가 프로세스에 보내는 비동기 메시지이며, trap을 사용하면 스크립트가 이에 의도적으로 대응할 수 있습니다.

스크립트를 엽니다.

nano long_process.sh

함수 정의 아래, 주요 로직이 시작되기 전에 trap 명령을 추가합니다.

#!/bin/bash

cleanup() {
  echo ""
  echo "Cleaning up temporary files..."
  rm -f temp_data.txt
  echo "Cleanup complete."
  exit
}

## Register the trap
## SIGINT = Ctrl+C
## EXIT = Any exit (success or failure)
trap cleanup SIGINT EXIT

## The rest of the script...
touch temp_data.txt
echo "Temporary file 'temp_data.txt' created."

echo "Process is running. Press Ctrl+C to stop..."
while true; do
  sleep 1
done

trap arguments 이해하기:

  • cleanup: 실행할 명령 또는 함수입니다.
  • SIGINT: Ctrl+C를 눌렀을 때 전송되는 신호입니다.
  • EXIT: 스크립트가 어떤 이유로든 종료될 때마다 동작하는 의사 신호입니다.

SIGINT와 EXIT를 함께 사용하면 정리 작업의 신뢰성이 높아집니다. SIGINT는 일반적인 키보드 중단을 처리하고, EXIT는 정상 종료와 여러 오류 상황에 대한 일반적인 안전장치를 제공합니다.

저장하고 종료합니다.

정리 작업 확인하기

이제 정리 메커니즘이 제대로 동작하는지 확인합니다.

스크립트를 실행합니다.

./long_process.sh

스크립트가 temp_data.txt를 만들고 실행을 시작합니다.

이제 Ctrl+C를 눌러 스크립트를 중단합니다.

다음과 같은 출력이 표시되어야 합니다.

^C
Cleaning up temporary files...
Cleanup complete.

마지막으로 파일이 삭제되었는지 확인합니다.

ls temp_data.txt

다음과 같은 오류가 반환되어야 합니다.

ls: cannot access 'temp_data.txt': No such file or directory

trap 명령이 중지 신호를 성공적으로 가로채고, 스크립트가 종료되기 전에 정리 코드를 실행했습니다.

이는 전문적인 스크립트 작성 습관입니다. 스크립트가 임시 상태를 만든다면 그 상태를 어떻게 삭제할지도 정의해야 합니다. trap은 Bash 가 이 작업을 위해 제공하는 주요 도구 중 하나입니다.

요약

이 실습에서는 Trap을 사용해 견고한 스크립트를 작성하는 방법을 배웠습니다.

  1. 신호: Ctrl+C가 프로세스에 SIGINT 신호를 보낸다는 점을 이해했습니다.
  2. Trap: trap을 사용해 신호를 감지하고 특정 코드를 실행했습니다.
  3. 정리: 시스템을 깨끗하게 유지하기 위해 정리 작업을 자동화했습니다.

전문적인 스크립트는 데이터 손상과 남은 파일을 방지하기 위해 항상 종료 상황을 처리합니다.