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

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Table of Contents


들어가며

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


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

...


signal 과 event

kill 은 용도에 맞지 않게 이름이 지어진 명령어중의 하나로 주요 용도는 event 가 발생했음을 프로세스에게 알리는 것이다.프로그래밍을 할때 참고할 수 있는 signal 의 종류는 signal 을 프로세스에 보내는 명령어입니다.


signal 은 software interrupt 의 일종으로 어떤 이벤트가 발생했음을 프로세스에게 알려주는 매커니즘입니다.


사용자가 인터럽트 키(Ctrl + C)를 눌렀거나 프로세스가 잘못된 메모리에 접근했을 경우가 이벤트 발생 예이며 프로세스는 해당 이벤트에 맞는 signal 을 전송받게 됩니다.


시그널은 숫자 1부터 시작하는데 숫자는 기억하기 어려우므로 의미있는 이름으로도 정의되어 있습니다.


리눅스의 목록은 /usr/include/signal.h 에 정리되어 있다. (실제 선언부는 OS 의 종류에 따라 signal.h 에서 별도로 include 할 수도 있다)또는 다음 명령으로 정의되어 있으며 다음 명령으로도 전체 시그널 목록을 확인할 수 있음있습니다

Code Block
$ 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
Note

시그널의 숫자와 의미는 유닉스의 표준중 하나인 POSIX(Portable Operating System Interface) 에 정의되어 있습니다.


signal handler

signal 발생은 비동기 작업이며 개발자는 프로그램을 만들 때 특정 시그널을 수신했을 때 실행되기를 바라는 함수(시그널 핸들러)을 등록할 수 있습니다.


시그널 핸들러를 특별히 지정하지 않았을 경우 커널에 기본 정의된 액션을 실행하며 기본 정의 액션은 시그널의 종류에 따라 다르며 기본 정의된 액션은 다음 표처럼 총 5가지입니다.



action 명기본 동작
TERM시그널을 수신한 프로세스 종료
IGN시그널 무시
CORE시그널을 수신한 프로세스를 종료하면서 코어 덤프(core dump) 파일 생성
STOP시그널을 수신한 프로세스 정지
CONT중지된 프로세스 재시작


signal handler 를 작성하지 않았을 경우 대부분의 기본 액션은 해당 프로세스 종료이며 프로세스에 시그널을 보내는 명령어가 kill 인 이유는 이때문입니다.


Expand
titlesignal 프로그래밍 예제
Code Block
#include <stdio.h>
#include <stdlib.h>
#include <signal.h> // sigaction(), sigsuspend(), sig*()
#include <unistd.h> // alarm()

void handle_signal(int signal);

int main() {
    struct sigaction sa;

    sa.sa_handler = &handle_signal;
    sa.sa_flags = SA_RESTART;
    sigfillset(&sa.sa_mask);

    // Intercept SIGHUP and SIGINT
    if (sigaction(SIGHUP, &sa, NULL) == -1) {
        perror("Error: cannot handle SIGHUP"); // Should not happen
    }

    if (sigaction(SIGUSR1, &sa, NULL) == -1) {
        perror("Error: cannot handle SIGUSR1"); // Should not happen
    }

    // Will always fail, SIGKILL is intended to force kill your process
    if (sigaction(SIGKILL, &sa, NULL) == -1) {
        perror("Cannot handle SIGKILL"); // Will always happen
        printf("You can never handle SIGKILL anyway...\n");
    }

    if (sigaction(SIGINT, &sa, NULL) == -1) {
        perror("Error: cannot handle SIGINT"); // Should not happen
    }
    for (;;) {
        printf("\nSleeping for ~3 seconds\n");
        do_sleep(3); // Later to be replaced with a SIGALRM
    }
}

void handle_signal(int signal) {
    const char *signal_name;
    sigset_t pending;

    // Find out which signal we're handling
    switch (signal) {
        case SIGHUP:
            signal_name = "SIGHUP";
            break;
        case SIGUSR1:
            signal_name = "SIGUSR1";
            break;
        case SIGINT:
            printf("Caught SIGINT, exiting now\n");
            exit(0);
        default:
            fprintf(stderr, "Caught wrong signal: %d\n", signal);
            return;
    }

    printf("Caught %s, sleeping for ~3 seconds\n"
           "Try sending another SIGHUP / SIGINT / SIGALRM "
           "(or more) meanwhile\n", signal_name);
}



kill -l 로 볼 수 있는 많은 시그널중이벤트보통 


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

...


참고

  • Unix signal handling example in C, SIGINT, SIGALRM, SIGHUP...

    Expand

    Gist
    urlhttps://gist.github.com/aspyct/3462238