はじめに

SSH 接続で時間の掛かるシェルスクリプトをバックグラウンドで走らせて帰りたいのに、SSH 接続を切るとジョブが死んでしまいます。SSH 接続に限らず目の前の OS からログアウトしたりターミナル エミュレータを終了しても同じ現象が起こります。

この症状は正常です。なぜなら、バックグラウンド ジョブを起動したプロセス(ログイン シェル)が子プロセスである該当のバックグラウンドジョブをハングアップ シグナル( HUP )によって終了させるからです。

シェルスクリプトを起動した親プロセスは子プロセスの終了状態を監視しています。ですからログアウトして親プロセスであるシェルが終了すると子プロセスはゾンビ プロセスとなってしまうので親プロセスとなるシェル(ログインシェル)は子プロセスであるバックグラウンド ジョブを kill ( kill -HUP ) するのです。

nohup コマンド

ジョブを kill されないようにするには nohup コマンドを使います。nohup コマンドは HUP シグナルを無視するようにプログラムを実行します。また標準出力、標準エラー出力はファイルになります。STDOUT, STDERR に出力データがなくてもファイルは作成されます。

nohup コマンドでバックグラウンドで走らせたいバッチ処理プログラムなどを実行すればログアウトしても kill されないのでプロセスは継続しますから心置きなく家へ帰れます。nohup コマンドは Linux 以外にも Unix 系の OS なら使えるでしょう。私は Mac OS X で確認しています。無ければ GNU の coreutils にあります。

例1 普通に使う

$ nohup ./abc.sh &

abc.sh の標準出力、標準エラー出力に送られたデータはプログラムを実行したディレクトリに nohup.out というファイル名で保存される。プログラムを実行したディレクトリに書き込み権限が無ければ $HOME/nohup.out に保存される。

例2 標準出力先を指定する

$ nohup ./abc.sh > out.log &

abc.sh の標準出力が out.log になる。標準エラー出力は nohup.out で保存先は例1と同様にプログラムを実行したディレクトリか $HOME になる。

例3 標準エラー出力先を指定する

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

abc.sh の標準出力が out.log になる。標準エラー出力は err.log です。

以上のようなコマンドを実行した後はログアウトして大丈夫です。心配なら再度ログインしてプロセスを確認してみましょう。

注意点

標準入力を閉じる

SSH でログインしている場合は3つの I/O ストリーム をリダイレクトしておきます。SSH 接続でバックグラウド ジョブを実行する場合、日常的に標準出力、標準エラー出力をリダイレクトしていると思いますがここで重要なのは標準入力を閉じておくことです。具体的には /dev/null にします。

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

詳しいことは SSH Frequently Asked Questions をご覧下さい。

バックグラウンド ジョブとして実行する

もうひとつ、nohup は実行したプログラムを自動的にバックグラウンド ジョブにするものではありません。バックグラウンドで実行するなら & を付けて実行するか bg コマンドを使いましょう。

実行中のプログラムを終了する

nohup で実行中のプログラムを終了させるにはプロセスIDを調べて kill コマンドで強制終了(kill -KILL)します。


最終更新日: 2014年05月03日(土) / カテゴリー: Unix, Linux

Back to top