trap 으로 시그널 제어하기 - Ctrl + C 를 눌렀을 때 특정 처리를 수행하고 종료시키기
on ShellScript
어떤 프로세스를 강제로 종료시키기 위해서는 일반적으로 Ctrl + C 를 이용하는데, 이는 프로세스에 SIGINT 시그널을 전달하는 것이다.
SIGINT 를 받은 프로세스는 일반적으로 그대로 종료되지만, 쉘스크립트에서는 trap
을 사용해 이에 대한 처리가 가능하다.
trap 은 따옴표 안에 사용자가 수행할 명령어들을 넣고, 마지막에 특정 시그널명을 넣어줌으로써 해당 시그널을 제어할 수 있다.
trap ' ~ ' INT
처럼 사용하며, 이는 INT 시그널에 대한 처리가 되는 것이다.
아래 예제는 무한 루프를 돌며 cnt 값을 증가시키는 간단한 프로그램인데, 사용자 인터럽트 발생 시 해당 값을 출력하고 프로그램을 exit 으로 종료시킨다.
#!/bin/bash
cnt=0
trap '
echo
echo $cnt
exit
' INT
while :
do
cnt=$(( $cnt + 1 ))
echo $cnt
sleep 1
done
만약 trap '' INT
처럼 따옴표 안에 아무것도 실행시키지 않을 경우, SIGINT가 발생하더라도 아무 일도 일어나지 않는다.
즉 trap 으로 특정 시그널에 대한 제어를 수행하긴 하는데, 아무것도 수행하지 않는 것이기 때문에 프로세스가 실질적으로는 Ctrl+C 를 무시하는 것이 된다.
아래처럼 아무리 ^C 를 입력해도 반응이 없음을 확인할 수 있다.
$ bash test.sh
1
2
^C^C^C3
^C^C^C^C^C4
^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C5
6
7
Killed
이렇게 exit 처럼 프로세스를 종료시키는 처리가 없을 경우에는, 다른 터미널에서 pid 를 확인한 뒤 강제적으로 죽여야 한다.
$ ps aux | grep test.sh
$ sudo kill -9 [PID]
또한 trap은 시그널을 캐치하는 것이기 때문에, nohup & 등으로 프로세스가 백그라운드에서 돌며 터미널을 종료해도 HUB 시그널이 전달되지 않을 경우는 trap 이 잡지 않는다.