본문 바로가기

서버운영 (TA, ADMIN)/리눅스

[리눅스] trap을 이용한 signal 처리

signal은 unix 운영체제에서 비동기적인 사건을 전송하기 위해서 사용하는 설비다. 비동기적인 사건이란 언제 발생할지 예측할 수 없는 사건으로 터미널 종료, 메모리 침범, 알람, 장치로부터의 입력 등의 사건이 이에 해당한다. 유닉스 시스템은 이러한 시그널 처리가 가능하도록 signal(:12) 제어용 C 함수들을 제공한다. 그러나 이들 C 인터페이스 함수는 간단한 일을 처리하기에는 좀 부담스러운게 사실이다. 여기에 trap(:12)을 이용해서 shell 스크립트로 이벤트를 처리하는 방법을 소개하고자 한다.

 

시그널은 프로세스에 종속적으로, 해당 프로세스별로 받아들이거나 무시하는 시그널이 정의된다. 그러므로 shell 상에서 이벤트를 처리하는 스크립트를 작성하려면, shell에서 받아들이는 시그널의 종류에 대해 알아볼 필요가 있다. 다음은 쉘에서 받아들여서 처리할 수 있는 시그널의 종류이다.

시그널 번호 시그널 이름 설명
0 EXIT 쉘의 종료
1 HUP 터미널이 종료되었을때 발생하는 시그널
2 INT Del 키를 눌렀을때 발생되는 시그널로 현재 프로그램의 중단을 의미한다.
3 QUIT Ctrl + \ 키를 누르면 발생되는 시그널로 현재 프로그램을 종료시킨다.
9 KILL 프로그램을 강제로 종료시키기 위해서 보내는 시그널로 무시하거나 추적해서 처리할 수 없다.
11 SEGV segmentation violation 에 발생되는 시그널이다. 유닉스를 프로세스가 사용하는 메모리 영역을 보호하는데, 다른 프로세스가 사용하는 메모리 영역을 침범하려고 할때 주로 발생한다.
15 TERM 이 시그널을 받은 프로세스는 종료가 된다. 기본적인 동작은 KILL 과 같지만 KILL 과는 다르게 무시할 수도 있고, 추적해서 처리할 수도 있다.

 

trap 명령어를 이용하면 쉘에서 발생하는 시그널을 처리하는 프로그램을 만들 수 있다. trap의 사용법은 다음과 같다.

trap command signals_list

 

다음은 INT 시그널이 발생할 경우 rm test.txt를 지우는 쉘스크립트다.

$ trap "rm test.txt" 2
$ echo $$
38500

 

$$는 쉘의 PID 값을 저장하고 있는 특수 변수다. 이제 다른 쉘을 띄워서 38500에 INT 시그널을 전송해본다.

$ kill -INT 38500

 

그럼 trap을 실행한 쉘에서 rm test.txt 명령이 실행되는 걸 확인할 수 있을 것이다. y/n을 물어보는 프롬프트가 뜨지 않고 바로 파일을 삭제시키려면 rm에 -f 옵션을 주면 된다.

 

다음은 ALRM 시그널이 발생할때마다 쉘의 HISTORY 변수 이름을 가지는 파일을 특정파일에 저장하는 일을 하는 스크립트다. 로그인한 사용자가 이전에 어떤 작업을 했는지 그 내용을 남기고자 할때 유용하게 사용할수 있을 것이다.

$ trap 'cp $HISTFILE $HOME/old_hist.bak; exit' ALRM