Linuxでのプロセスの管理(bg,fg,disown)

仕事でちょっと質問されて最近はこういうの知らない人もいるんだなぁってことで纏めておく。
いいネタだし、自分も最後に紹介するコマンドをど忘れしていたというのもある。
そもそもの質問は、バッチ処理を走らせているんだがログアウトしたらプロセスが死ぬのを何とかしてバックグラウンドで走らせておきたい、というよくある話。


まず、ログインしている状態でのプロセスの操作から。

$ hoge.sh

とかしてこのプロセスが動き続けているとする。


まず、Ctrl+Zするとプロセスがサスペンドという一時停止状態になる。
この状態でfgコマンドでフォアグランドに戻り動作を再開する。
bgならばバックグランドのままで動作を再開する。
これらはジョブというshellの処理単位として管理されている。
ジョブの状態を確認するには、"jobs"コマンドを使用します。


さてCtrl+Zの動作だが、これは内部的にはプロセスにSIGTSTPが送られている状態になる。manページを見るとこのように書いてある。

$ man 7 signal
〜省略〜
IGTSTP    18,20,24   Stop   端末 (tty) より入力された一時停止 (stop)
シグナル SIGKILL と SIGSTOP はキャッチ、ブロック、無視できない。
〜省略〜


何も知らない人はここで、ログアウトしてもバックグランドに移動したプロセスは死なないと思うが実際はログアウトした瞬間にプロセスは死ぬ。
これは、プロセスの親子関係を知らないからだ。ここで"hoge.sh"プロセスはログインしたshell上から起動されるのでshellの子プロセスとなっている。
疑う人はpstreeコマンドを実行すればよい。
Unix系OSのプロセスの特徴として親プロセスが死ぬと、子プロセスも死ぬ。
pstreeを見るとすべてのプロセスの親をたどってくとinitというプログラムに突き当たる。これはLinux Kernelが起動して最後の処理としてこのinitプログラムを起動して、initがその後の起動処理を行うためだからだ。
つまり、"pkill -kill init"とかするとPCが落ちてしまう。シャットダウンも同じ原理を利用している。


さて話を戻すと"bg"しただけではログアウトしてはダメだ。
そこで、"disown"コマンドがある。これを利用すればプログラムを親プロセスから切り離して独立したプログラムにしてくれる。

$ disown jobid

あとはログアウトしてもOKだ。


ちなみに、プロセスを実行する前にこのような処理をしたいと分かっていれば"nohup"コマンドがある。

$ nohup ./hoge.sh &