Child pages
  • Unix, Linux 에서 kill 명령어로 안전하게 프로세스 종료 시키는 방법

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 5 Next »


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


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


kill 명령어

kill 은 용도에 맞지 않게 이름이 지어진 명령어중의 하나로 주요 용도는 event 가 발생했음을 프로세스에게 알리는 것이다.

프로그래밍을 할때 참고할 수 있는 signal 의 종류는 /usr/include/signal.h 에 정리되어 있다. (실제 선언부는 OS 의 종류에 따라 signal.h 에서 별도로 include 할 수도 있다)

또는 다음 명령으로 시그널 목록을 확인할 수 있음. 


$ kill -l

1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP
 6) SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR1
11) SIGSEGV     12) SIGUSR2     13) SIGPIPE     14) SIGALRM     15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO       30) SIGPWR



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 $@


같이 보기