バックグラウンドプロセス(ジョブ)の管理

ログインして対話的に使う分にはなんら問題はないのですが、ずっと動かしっぱなしのプロセスはどうするのかな、という疑問が出てきました。動かしてるプロセス分ターミナルを立ち上げてるというのも現実的じゃないし、screen で複数プロセス動かすのもありかもしれないけど、ちょっと違うような気がするし、そもそもログアウトしてプロセスがなくなっちゃったらまずいし。ということで、自分のやりたいことを念頭において調べてみました。
※ 以下の説明では、バックグラウンドプロセスのことを「ジョブ」と書くことがあります。

まとめ

  • &    コマンドラインの最後に'&'を付けるとバックグラウンドで起動
  • jobs  いま動いているバックグラウンドプロセスの一覧を表示
  • fg   バックグラウンドプロセスをフォアグラウンドへ移す
  • bg   バックグラウンドプロセスを実行する
  • kill  バックグラウンドプロセスを強制終了させる
  • Ctrl+Z プロセスの中断(バックグラウンドに限らず有効)

バックグラウンドプロセスとして実行

コマンドラインの最後に '&' を付けるとバックグラウンドでの実行になります。

$ cat > xxx &
[1] 27479
$
[1]+  Stopped                 cat > xxx

[1]はジョブ番号、27479はプロセスIDです。ジョブ番号を指定するときは %1 で、プロセスIDはそのまま使えます。
プロンプトは出ていませんが、この状態でもうバックグラウンドで「cat > xxx」プロセスが走って、フォアグランドに戻ってきています。試しに la してみると、0バイトで xxx というファイルができています。

[1]+  Stopped                 cat > xxx
la
 total 84
 drwxr-xr-x 7 mam  4096 2008-06-09 05:49 ./
 drwxr-xr-x 9 root 4096 2008-04-29 06:18 ../
 -rw-r--r-- 1 mam     0 2008-06-09 05:49 xxx

あと1つ、「cat > yyy &」もバックグラウンドで走らせてみます。

バックグラウンドプロセスの確認

$ jobs
[1]-  Stopped                 cat > xxx
[2]+  Stopped                 cat > yyy

jobs でバックグラウンドで実行(停止)中のプロセスの一覧が表示されます。"+"はカレント・ジョブ、"-"は前のジョブです。それより前のジョブのこの欄は空白です。

バックグラウンドプロセスをフォアグラウンドへ

$ fg
cat > yyy

fg でカレント・ジョブをフォアグラウンドへもってきます。「cat > yyy」へ実行が移りました。文字を入力すると、それが yyy へ書き込まれます。プロセスを中断するには Ctrl+Z を入力します。

cat > yyy
 ← ここで Ctrl+Z を入力
[2]+  Stopped                 cat > yyy
$

バックグラウンドプロセスを実行する

cat の例だとわかりづらいので新しい例で説明します。

$ sleep 10
 ← ここで Ctrl+Z を入力
[1]+  Stopped                 sleep 10
$ bg %1
[1]+ sleep 10 &
$ jobs
[1]+  Running                 sleep 10 &
$
[1]+  Done                    sleep 10

フォアグラウンドで動かした「sleep 10」を Ctrl+Z で中断します。この時点で中断されたプロセスは、Stopped 状態のバックグラウンドプロセスになります。
これを「bg %1」で実行(リスタート)すると、バックグラウンドプロセスのまま、Running 状態になります。「sleep 10」の実行が終了すると最後の行( Done )が返されます。

バックグラウンドプロセスの強制終了

kill でバックグラウンドプロセスを強制終了させることができます。

$ sleep 10
 ← ここで Ctrl+Z を入力
[1]+  Stopped                 sleep 10

$ jobs -pl
[1]+ 27765 Stopped                 sleep 10
$ kill %1
$[1]+  Terminated              sleep 10
$ jobs
$

bg では「bg %1」でも「bg 1」でも同じでしたが、kill はそういうわけにいきませんので要注意。

$ jobs -pl
[1]+ 27765 Stopped                 sleep 10
[2]- 27767 Stopped                 sleep 20
$ kill 27765
$ kill 1
bash: kill: (1) - Operation not permitted
$ kill %1
$[1]+  Terminated              sleep 10
$ kill -9 27767
$[1]+  Killed                  sleep 20

ジョブ番号(%)を指定します。%を付けないと通常のプロセスIDでの killになってしまうので、思いもよらぬサービスを killしてしまわないように気をつけましょう。
プロセスIDを指定しても killできますが、Killシグナル( -9 )を付けないと 強制終了はできないようです。

プロセスの中断

Ctrl+Z でプロセスを中断できます。フォアグラウンドで実行中のプロセスを中断するとそのプロセスは自動的に Stopped 状態のバックグラウンドプロセスになります。
「stop %」でバックグラウンドプロセスの停止ができるはずですが、うちの環境では「stop: Need to be root」ということで停止できず、じゃあ「sudo stop %1」とかやると「stop: Unknown job: %1」と言われてやっぱり停止できず。fg して Ctrl+Z で停止できるので深いところまでは調査せず。

jobs [-lrs] [%jobid]

  • -l   プロセスIDも表示
  • -r   実行中のジョブだけ表示
  • -s   停止中のジョブだけ表示
  • %jobid jobidで指定したジョブだけ表示

ログアウトしてもバックグラウンド ジョブを継続する方法

詳しくはこちら(→ログアウトしてもバックグラウンド ジョブを継続する方法)を見ていただくとして要点だけ。

$ nohup ./abc.sh > out.log 2> err.log < /dev/null &

SSH でログインしている場合は、標準出力、標準エラー出力をリダイレクトして、標準入力を閉じておく、ことだそうです。
ただ単に「$ nohup ./abc.sh &」としただけでも、標準出力、標準エラー出力に送られたデータは「プログラムを実行したディレクトリ」に nohup.out というファイル名で保存されるということですから、これからいろいろと試してみます。