쉘기능을 자유자재로 다루기_04 이상 종료해도 흔적을 남기지 않도록 종료 시 작업 파일을 삭제하는 뒷처리하기

 
  • 출처 : 유닉스 리눅스 쉘스크립트 예제사전_한빛미디어

명령어: trap, rm
키워드: 임시 파일, 종료, 시그널, 트랩
사용처: 임시 파일을 사용하는 스크립트에서 정상 종료든 강제 종료든 상관없이 공통된 종료 처리를 하고 싶을 때


실행예제

$ ./sig-exit.sh
^C  <----------------------------------- Ctrl + C로 강제 종료해도
$ ls
sig-exit.sh calcA.sh calcB.sh  <-------- 임시 파일은 남아 있지 않음

스크립트

#!/bin/sh

# 임시 파일을 정의, 빈 파일로 초기화
tmpfile="calctmp.$$"  #-------------------- 1
: > "$tmpfile"  #-------------------------- 1

# 트랩 설정. 종료할 때 임시 파일 삭제
trap 'rm -f "$tmpfile"' EXIT  #------------ 2

# 오래 걸리는 계산을 하는 외부 스크립트 실행
./calcA.sh >> "$tmpfile"  #---------------- 3
./calcB.sh >> "$tmpfile"  #---------------- 3

# 계산 결과를 더해서 최종 합계를 계산
awk '{sum += $1} END{print sum}' "$tmpfile"

   

해설

이 스크립트는 정상으로 종료했을 때는 물론이고, 키보드에서 Ctrl + C를 입력해 강제 종료했을 때도 임시 파일(tmpfile)을 삭제하고 종료합니다. 그리고 bash를 사용한다고 전제합니다.

이 스크립트는 어떤 계산을 할 때 그 결과를 출력하는 외부 스크립트 calcA.sh와 calcB.sh를 사용합니다. 이 스크립트들은 다음처럼 단순히 계산 결과를 표시한다고 가정합니다.

$ ./clacA.sh
3928

$ ./calcB.sh
79104

이 예제의 마지막에 calcA.sh와 calcB.sh로 출력한 두 값을 더한 수를 계산하고 싶다고 가정합니다. 그리고 처리에 시간이 걸려서 강제 종료 등을 할 때 쓰레기 파일이 남지 않도록 임시 파일을 삭제합니다. 따라서 스크립트 종료 시 임시 파일을 삭제하는 명령어를 실행합니다.

스크립트 종료 시 공통 처리를 작성하고 싶다면 trap 명령어를 써서 EXIT 시그널을 사용하는 방법이 일반적입니다. EXIT 시그널이란 bash에서 사용 가능한 유사 시그널로 정상 종료(스크립트가 마지막까지 실행되거나 exit 명령어로 명시적으로 종료)나 강제 종료(Ctrl + C 입력이나 kill 명령어로 종료) 모두에서 발생합니다. 따라서 EXIT 시그널으로 끼어들기 처리를 해서 임시 파일을 삭제하면 스크립트 종료 시 임시 파일을 확실히 삭제할 수 있게 됩니다.

예제에서는 1에서 계산 결과를 임시로 보관할 파일의 이름을 정의합니다. 이때 :(널 명령어)을 써서 빈 파일을 만듭니다. calctmp.$$는 임시 파일을 만들 때 파일명에 프로세스 ID를 넣는 기법입니다.

2에서는 EXIT 시그널 설정을 trap 명령어로 지정합니다. 여기서 종료 시 임시 파일을 삭제하도록 rm 명령어로 임시 파일 $tmpfile을 삭제합니다. 이렇게 하면 스크립트 종료 시 trap 설정한 명령어가 실행되어 임시 파일이 자동으로 제거됩니다.

3에서 임시파일에 계산 결과를 출력합니다. 이 예제에서는 계산에 오랜 시간이 걸려서 도중에 강제 종료한다고 가정합니다.

4는 임시 파일로 최종 계산을 합니다. awk 명령어로 임시 파일 첫 번째 컬럼값을 꺼내서 sum이란 변수에 더하기를 해서 표시하면 최종값이 됩니다. 스크립트가 4까지 실행되면 정상 종료의 EXIT 시그널이 발생해서 임시 파일을 삭제합니다. 또한 계산 도중에 Ctrl + C를 입력해서 강제 종료하더라도 역시 EXIT 시그널이 발생해서 임시 파일을 삭제하게 됩니다.

이렇듯 정상 종료, 강제 종료 관계없이 공통된 종료 처리를 작성할 수 있습니다. 임시 파일을 확실하게 삭제하고 싶을 때 사용하면 되겠지요.

bash 유사 시그널

여기서 다룬 EXIT 시그널은 bash에서 사용 가능한 유사 시그널입니다. 보통 시그널은 OS가 발생시켜 관리하지만 유사 시그널은 bash가 발생시키고 받는 것도 bash 프로세스뿐입니다. 셸 스크립트를 작성할 때 어느 쪽 시그널이라도 trap 명령어로 동등하게 취급하므로 이런 유사 시그널인지 진짜 시그널인지 신경쓰지 않아도 됩니다.

bash에서 사용하는 시그널은 다음과 같습니다. 예를 들어 ERR 시그널을 사용하면 에러가 발생할 때마다 특정 함수를 실행하는 처리를 간단히 만들 수 있습니다.

  • bash 유사 시그널

    유사 시그널 발생 타이밍
    EXIT 스크립트 종료 시
    ERR 명령어 종료 스테이터스가 0이 아님
    DEBUG 명령어가 실행됨
    RETURN .(닷 명령어) 또는 soure 명령어로 외부 스크립트 호출