시스템 작업하던 직원이 java 관련 프로세스 종료를 kill -9 PID 를 하는 것을 보고 의아해서 물어보니 당연히 그렇게 하는 걸로 알고 있었다.

 

검색을 해 보니 거의 모든 블로그가 프로세스 종료를 -9 signal 로 처리하라고 되어 있어서 kill 명령의 의미 및 안전하게 프로세스 종료 하는 법을 정리해 본다.

 

kill 은 용도에 맞지 않게 이름이 지어진 명령어중의 하나이다. 주요 용도는 event 가 발생했음을 프로세스에게 알리는 것이다. signal 의 종류는 /usr/include/signal,h 에 정리되어 있다. (실제 선언부는 OS 의 종류에 따라 signal.h 에서 별도로 include 할 수도 있다)



Un*x 는 프로그램에서 signal 종류 별로 signal handler 를 지정할 수 있는데 유일하게 handler 를 지정할수 없는 시그널은 SIGKILL(9), SIGSTOP(19) 두 개의 시그널이다.

제대로 구현한 프로그램이라면 종료의 의미로 사용되는 signal (INT, HUP, TERM 등)을 받으면 resource 를 정리하는 cleanup 코드를 실행하고 종료하게 되어 있을 것이다.

프로세스 종료시 kill -9 PID 를 권장하는 않는건 제대로 signal handler 를 구현한 프로그램이라도 cleanup 작업을 하지 못하고 바로 종료되어 버릴수 있기 때문이다.

 

개인적으로 추천하는 방법은 먼저 kill -TERM PID 나 kill -HUP PID 같이 TERM(Termination) 나 HUP(Hangup) signal 을 날리는 것이다.

위의 signal을 날리면 제대로 된 프로그램은 보통 cleanup 코드를 수행하고 종료하게 구현되어 있다.

Java JRE 도 TERM 이면 깨끗하게 종료되니 tomcat 이나 기타 java 관련 프로그램 종료시 KILL(9)을 먼저 보내지 말고 두 세번 정도 TERM(15) 보내는 방법을 추천한다. (Linux의 service 명령어도 TERM 을 보내보고 안 죽으면 KILL 을 보내게 구현되어 있다)

여러개의 프로세스를 종료시킬 경우 다음과 같은 awk script 를 이용해서 종료할 수 있다.

ps -eaf PROCESS_NAME|grep -v grep|awk '{print "kill -TERM "$2}' | sh -x

httpd 를 종료할 경우 다음과 같이 수행하면 된다.

ps -eaf httpd|grep -v grep|awk '{print "kill -TERM "$2}' | sh -x

위의 script 를 두 세번 실행해 보고 종료가 되지 않는 process 가 있다면 SIGTERM 대신 SIGKILL 을 사용하면 된다.

 


모든 child process 까지 종료시키는 스크립트가 필요하다면 StackOverflow의 Best way to kill all child processes 쓰레드를 참조하자.

위 쓰레드에서 발췌한 killtree.sh
#!/bin/bash
 
killtree() {
    local _pid=$1
    local _sig=${2:-TERM}
    kill -stop ${_pid} # needed to stop quickly forking parent from producing child between child killing and parent killing
    for _child in $(ps -o pid --no-headers --ppid ${_pid}); do
        killtree ${_child} ${_sig}
    done
    kill -${_sig} ${_pid}
}
 
if [ $# -eq 0 -o $# -gt 2 ]; then
    echo "Usage: $(basename $0) <pid> [signal]"
    exit 1
fi
 
killtree $@


+ Recent posts