プロセスとシグナル

INPUT · スライド

合図を送って止める(`kill`)

01 / 08

kill は「殺す」ではない

名前がおどろおどろしいけれど、kill がやっているのはこれだけだよ。

> プロセスに合図を1つ送る

合図のことを シグナル(signal)と呼ぶよ。手紙を1通投げこむようなものだね。

受け取ったプロセスがどうするかは、そのプロセスが決めるんだ。片づけて終わることもあるし、無視することもある。

~ $ kill 84

これは「84番さん、終わってくれませんか」というお願いだよ。命令ではないんだ。

名前が kill なのは、既定の合図がたいてい「終わる」結果になるからだね。歴史のいたずらだと思ってほしいな。送っているのは合図だけ、これが今日いちばん大事なところだよ。

02 / 08

合図には名前と番号がある

合図の一覧は kill -l で見られるよ。33種類あるんだ。

~ $ kill -l 1) HUP 2) INT 3) QUIT ... 9) KILL ...15) TERM

覚えるのは4つだけで足りるよ。

番号名前意味
15TERM「片づけて終わってね」(既定)
9KILL問答無用で消す
2INTCtrl-C を押したときのこれ
1HUP「設定を読み直して」に使われる

書き方は3通りあるよ。どれも同じだね。

kill 84         既定(TERM)kill -15 84     番号で書くkill -TERM 84   名前で書く

名前で書くほうが読みやすいけれど、-9 だけは番号のまま使われることが多いよ。「ナインを送る」と言えば通じるくらい、有名な番号なんだ。

03 / 08

TERM は「お願い」

既定の TERM は、受け取ったプロセスに考える余地を残す合図だよ。

よくできたプログラムは、TERM を受け取るとこうするんだ。

1. 書きかけのファイルを保存する
2. 開いているものを閉じる
3. 一時ファイルを片づける
4. それから終わる

この片づけを 後始末 と呼ぶよ。だからまず TERM を送るのが作法なんだ。

kill 84        ← まずこれ

逆に、片づける余地を与えずに消すと何が起きるだろう。書きかけのファイルが半分だけ残ったり、一時ファイルが散らかったり、データベースなら壊れることもあるよ。

急いでいるときほど TERM から。これは本物のサーバーを触るときの基本の作法だよ。

04 / 08

KILL は最後の手

TERM を無視するプログラムもあるよ。無限に回っていて手紙を読む余裕が無い、という場合もある。

そのときの最後の手が -9(KILL)だよ。

kill -9 84

これはプロセスに届かないんだ。カーネルが直に消してしまうので、受け取る側は何もできない。

TERM  → プロセスに届く → 好きにできるKILL  → カーネルが消す → 抵抗できない

だから確実に消える。でも後始末は1つも走らないんだ。

手順を覚えておこう。

1. kill PID          お願いする2. 数秒待って確かめる3. まだ生きていたら kill -9 PID

最初から -9 を打つ癖がついている人は多いけれど、それは毎回コンセントを抜いて電源を切るようなものだよ。たいてい平気だけれど、壊れる日が来るんだ。

05 / 08

相手の指し方は3通り

誰に送るかの書き方は3通りあるよ。

kill 84                 番号で指すkill %1                 ジョブ番号で指すkillall sleep           名前で全部指す

番号を調べるには、前のレッスンの道具が使えるね。

kill $(pidof yes)       名前から番号を引いて渡す

$( ) は「中を実行して結果をここに置く」書き方だったね。

killall は便利だけれど気をつけてね。同じ名前のものを全部止めるからだよ。自分に関係ないものまで巻きこむことがあるんだ。

もう1つ、送らずに生きているかだけ確かめる書き方があるよ。

kill -0 84

-0 は「0番の合図」つまり何も送らないという意味で、相手がいるかどうかだけが返ってくるんだ。生きていれば 0、いなければ 1 だよ。点検のスクリプトでよく使う形だね。

06 / 08

Ctrl-C も合図だった

あなたはもう合図を送ったことがあるよ。Ctrl-C だね。

~ $ sleep 30(返ってこない)^C~ $

このとき送られているのが INT(2番)だよ。「割りこみます」という合図だね。

仕組みはこうだよ。Ctrl-C を押すと、端末がいま前で動いているプロセスに INT を送る。だから kill -2 番号 と打ったのと同じことなんだ。

他にもキーで送れる合図があるよ。

キー合図意味
Ctrl-CINTやめてほしい
Ctrl-ZTSTPいったん止めて(次のレッスンで)
Ctrl-\QUITやめて、記録も残して

ボタンの裏で何が起きていたかが見えたね。魔法ではなくて、番号を持った合図が飛んでいただけなんだ。

07 / 08

止まったかどうかは番号で分かる

合図で終わったプロセスは、終わり方が終了ステータスに残るよ。

~ $ timeout 2 sleep 10Terminated~ $ echo $?143

143 という数に意味があるよ。128 + 15 だね。15 は TERM の番号だよ。

128 + 合図の番号 = 終了ステータス128 + 15(TERM) = 143128 +  9(KILL) = 137128 +  2(INT)  = 130

この3つは現場でよく見る数字だよ。ログに 137 を見つけたら、誰か(かカーネル)が -9 で消したと読めるんだ。メモリ不足でカーネルが消したときも 137 になるので、原因を探す手がかりになるよ。

timeout 秒 コマンド は「決めた時間で打ち切る」道具だよ。中では時間が来たら TERM を送っているんだ。-s KILL を付ければ KILL を送るので、137 になるよ。

終了ステータスそのものは章11でたっぷりやるからね。ここでは「数から死因が読める」ことだけ覚えておいて。

08 / 08

さあ、打ってみよう

使う道具はこれだけだよ。

kill 番号        TERM を送る(お願い)kill -9 番号     KILL を送る(強制)kill -0 番号     生きているかだけ見るkill %1          ジョブ番号で指すkill -l          合図の一覧killall 名前     名前で全部止めるtimeout 秒 ...   時間で打ち切る

ホームには gaman.sh を置いてあるよ。TERM を受け止めて終わらないスクリプトだよ。これで「お願いが効かない相手」を体験してもらうんだ。

中身はこうなっているよ。

trap "echo きかないよ" TERMwhile true; do sleep 1; done

trap が「TERM が来たらこれをやる」という指定だね。書き方は章11でやるので、いまは読めなくていいよ。

止める相手は sleepyes のような無害なものだけにしてね。kill 1 は打っても効かないように守られているけれど、本物のサーバーでは機械が止まるからね。