Ctrl+C と killコマンド の違い

kill : 指定されたプロセスにのみシグナルを送信(プロセスの親子は関係ない)
Ctrl+C : フォアグラウンドのジョブの全プロセスに対してSIGINTを送信

[実験]

以下のようなスクリプトを実行させ、killした場合とCtrl+Cした場合とで挙動の違いを見る。

[user1@vm03 shtest]$ cat hoge.sh
#!/bin/sh

sleep 180
killコマンドの場合

hoge.sh を実行


[user1@vm03 shtest]$ ./hoge.sh

別端末からプロセスを確認


[user1@vm03 ~]$ ps jx
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
4410 4411 4411 1966 pts/0 4583 S 501 0:00 -bash
4437 4438 4438 2029 pts/1 4585 S 501 0:00 -bash
4411 4583 4583 1966 pts/0 4583 S+ 501 0:00 /bin/sh ./hoge.sh
4583 4584 4583 1966 pts/0 4583 S+ 501 0:00 sleep 180
4438 4585 4585 2029 pts/1 4585 R+ 501 0:00 ps jx
hoge.sh のプロセスとsleep のプロセスが両方ある。PGIDは同じ。

hoge.sh のプロセスをkillで殺す。


[user1@vm03 ~]$ kill 4583

もう一度プロセスを確認


[user1@vm03 ~]$ ps jx
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
4410 4411 4411 1966 pts/0 4411 S+ 501 0:00 -bash
4437 4438 4438 2029 pts/1 4587 S 501 0:00 -bash
1 4584 4583 1966 pts/0 4411 S 501 0:00 sleep 180
4438 4587 4587 2029 pts/1 4587 R+ 501 0:00 ps jx
→ sleep プロセスが残った。sleep プロセスの親プロセスのPID は1。つまり init プロセス。

なお、killコマンドはシグナル番号が指定されなかった場合、デフォルトでSIGTERM (シグナル番号:15)を送る。

Ctrl+C の場合

hoge.sh を実行


[user1@vm03 shtest]$ ./hoge.sh

別端末からプロセスを確認


[user1@vm03 ~]$ ps jx
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
4410 4411 4411 1966 pts/0 4591 S 501 0:00 -bash
4437 4438 4438 2029 pts/1 4593 S 501 0:00 -bash
4411 4591 4591 1966 pts/0 4591 S+ 501 0:00 /bin/sh ./hoge.sh
4591 4592 4591 1966 pts/0 4591 S+ 501 0:00 sleep 180
4438 4593 4593 2029 pts/1 4593 R+ 501 0:00 ps jx
hoge.sh のプロセスとsleep のプロセスが両方ある。PGIDは同じ。

元の端末でCtrl+C でhoge.sh を中断する。


[user1@vm03 shtest]$ ./hoge.sh
^C

もう一度hoge.sh のプロセスを確認


[user1@vm03 ~]$ ps jx
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
4410 4411 4411 1966 pts/0 4411 S+ 501 0:00 -bash
4437 4438 4438 2029 pts/1 4595 S 501 0:00 -bash
4438 4595 4595 2029 pts/1 4595 R+ 501 0:00 ps jx
hoge.sh も sleep プロセスもなくなっている。hoge.sh と同じPGID (PGID:4591) のプロセスに対してすべてSIGINT (シグナル番号:2)が送られたため。

PGIDが同じプロセス群は「プロセスグループ」という。これは時には「ジョブ」とも呼ばれる。

どうして送られたシグナルがSIGINTであるとわかるか


[user1@vm03 shtest]$ stty -a
speed 38400 baud; rows 35; columns 90; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = ; eol2 = ;
:
→ intr = ^C; が、Ctrl+C でSIGINTを送信するということを意味する。

[まとめ]

kill : 指定されたプロセスにのみシグナルを送信(プロセスの親子は関係ない)
Ctrl+C : フォアグラウンドのジョブの全プロセスに対してSIGINTを送信

参考:http://equj65.net/tech/linuxprocessgroup/