kill

kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]

Signals table 을 보면 알 수 있겠지만 대부분의 신호들은 치명적인 오류를 나타내고 default action 으로 프로세스가 종료됩니다. 그러므로 왜 신호를 보내는 명령 이름이 kill 인지 짐작을 할 수 있습니다. kill 명령으로 신호를 보낼때 신호값을 주지 않으면 기본값 또한 TERM 신호가 됩니다.

다음은 kill 명령 사용 예입니다. 신호명 앞에 SIG 를 제외하고 사용할 수 있고 소문자로 쓸 수도 있습니다. 또한 pid 대신에 jobspec 을 사용할 수 있습니다.

kill -TERM 4287

kill -SIGTERM 4287

kill -s TERM 4287

kill -s SIGTERM 4287

kill -n 15 4287

kill -15 4287

kill 4287         # 신호값을 주지 않으면 기본값은 TERM 신호가 된다.

kill 신호값 -PGID

kill 명령을 이용해 process group 에 신호를 보낼 수 있습니다.
이때는 PGID 앞에 - 문자를 붙여 사용합니다.

kill -TERM -4287

# 다음과 같은 경우는 -4287 값이 PGID 가 아니라 신호값을 나타내는 인수로
# 인식되는 것을 방지하기 위해 -- 를 붙입니다.
# 신호값을 주지 않았으므로 기본값인 TERM 신호가 됩니다.
kill -- -4287

kill -0 PID

신호값이 0kill -0 명령은 실질적으로 신호를 보내지 않지만 프로세스가 아직 살아있는지, 살아있다면 신호를 보낼수있는 권한이 되는지 테스트 하는데 사용합니다.

$ kill -0 32630; echo $?                # process 가 살아있고 신호를 보낼 수 있는 권한이 됨
0                                           

$ kill -0 32631; echo $?                # process 가 존재하지 않음
bash: kill: (32631) - No such process       
1

$ kill -0 1; echo $?                    # process 가 존재하지만 신호를 보낼 수 있는 권한이 안됨
bash: kill: (1) - Operation not permitted   
1

다음은 kill 명령을 활용하여 5 초마다 dd 명령의 진행 상태를 출력합니다.

실행중인 dd 명령에 USR1 신호를 보내면 현재 진행 상태를 stderr 로 출력합니다.

# 처음 dd 명령은 데이터를 stdout 으로 출력하므로 파이프를 통해 계속 전달되고
# USR1 신호에 의한 stderr 출력은 grep 명령을 거쳐 터미널에 보여지게 됩니다.

dd bs=1M if=$lv-snapshot 2> >( grep 'copied' >&2 ) |
    gzip --fast | ssh $DEST "gzip -d | dd bs=1M of=$lv" &

PID=(jobs -p)     # jobs -p 는 파이프로 연결된 명령 그룹일 경우 첫번째 명령의 PID 를 출력

while kill -0 $PID; do
  kill -USR1 $PID
  sleep 5
done

PID 가 0 일경우

스크립트 실행 중에 특정 상황에서 자기 자신을 종료해야 될 때가 있습니다. 그런데 background 프로세스가 생성되어 실행 중이거나 스크립트 내에서 a.sh -> b.sh -> c.sh 순서로 호출하여 실행중에 있을경우 단순히 exit 명령을 사용하거나 kill -TERM $$ 을 하는 것으로는 c.sh 만 종료가 되고 a.sh, b.sh 와 background 프로세스는 실행을 계속하게 됩니다.

이때 사용할 수 있는 것이 kill -TERM 0 입니다. PID 로 0 을 사용하면 kill 명령을 호출한 프로세스와 같은 프로세스 그룹에 속한 모든 프로세스에게 신호가 전달됩니다. 따라서 c.sh 에서 kill -TERM 0 명령을 실행하면 같은 프로세스 그룹에 속한 a.sh, b.sh, c.sh 와 background 프로세스가 모두 신호를 받고 종료하게 됩니다.

# 스크립트 자신의 PGID 에 TERM 신호 보내기
kill -TERM 0          # kill -TERM -$$
kill 0                # kill -- -$$
----------------------------------

# 스크립트 자신의 PGID 에 INT 신호 보내기
kill -INT 0
$ cat a.sh              $ cat b.sh              $ cat c.sh
#!/bin/bash             #!/bin/bash             #!/bin/bash

echo start a.sh         echo start b.sh         echo start c.sh 

./b.sh                  ./c.sh                  sleep 100 &      # background 실행
                                                kill -TERM $$    # $$ 사용
echo end a.sh           echo end b.sh         
                                                echo end c.sh

# a.sh 를 실행해 보면 c.sh 만 종료가 되고 나머지는 종료되지 않는다.
$ ./a.sh 
start a.sh
start b.sh
start c.sh
Terminated    # c.sh 만 종료되고
end b.sh      # 나머지는 종료되지 않는다.
end a.sh

$ ps ax | grep slee[p]    # background 로 실행된 sleep 프로세스도 남아있다
 4643 pts/14   S      0:00 sleep 100

# 이번에는 c.sh 의 'kill -TERM $$' 을 'kill -TERM 0' 로 변경한 후 실행해보면
# 같은 PGID 갖는 프로세스들이 모두 종료되는 것을 볼 수 있습니다.
$ ./a.sh 
start a.sh
start b.sh
start c.sh
Terminated

$ ps ax | grep slee[p]
$