shell終了後にバックグラウンドプロセスが閉じる理由


http://doc.okbase.net/leehomjan/archive/107550.html
linuxでテストを行うと、バックグラウンドプロセスが開始された後、exitを使用してログインshellを終了すると、shellが終了してもバックグラウンドプロセスは正常に動作しますが、ログインしたウィンドウを直接閉じる(xshellを直接閉じるなど)と、バックグラウンドプロセスは一緒に終了します.すべてログインを終了するのはなぜ前者のバックグラウンドプロセスが終了し、後者は終了しないのですか?
bashのmanualを表示すると、次の説明があります.
The shell exits by default upon receipt of a SIGHUP. Before exiting, an interactive shell resends the SIGHUP to all jobs, running or stopped. Stopped jobs are sent SIGCONT to ensure that they receive the SIGHUP.
これにより、バックグラウンドプロセスの終了は、shellにログインしてSIGHUP信号を受信した後、終了前にSIGHUPをすべてのジョブ(jobs)に転送するためであることが分かる.ジョブはSIGHUP受信により運転を終了する.
では、設定によって、ウィンドウが異常に閉じたときにバックグラウンドプロセスを継続して実行できますか?
答えは肯定的で、一般的に以下の4つの方法があります.
1.nohupを使用してコマンドを実行する
# nohup ./back.sh &
# nohup ./fore.sh
^Z
[2]+  Stopped                 nohup ./fore.sh
# jobs 
[1]-  Running                 nohup ./back.sh &
[2]+  Stopped                 nohup ./fore.sh
# ps -o pid,ppid,pgid,sid,cmd
  PID  PPID  PGID   SID CMD
 4766  4716  4766  4716 /bin/bash ./back.sh
 4769  4716  4769  4716 /bin/bash ./fore.sh
# fg
nohup ./fore.sh

###           ###

# ps -eo pid,paid,pgid,sid,cmd |grep -E "back|fore"
 4766     1  4766  4716 /bin/bash ./back.sh
 4769     1  4769  4716 /bin/bash ./fore.sh

再ログイン後もフロントプロセスとバックグラウンドプロセスは実行されていますが、親プロセスはinitになります.
nohupは現在のディレクトリの下でnohup.outファイルを生成し、実際のコマンドの標準出力と標準エラーをnohup.outにリダイレクトします.
 
2.setsidでコマンドを実行する
# setsid ./back.sh &
# setsid ./fore.sh
# jobs 
# ps -eo pid,ppid,pgid,sid,cmd |grep -E "back|fore"
 4871     1  4871  4871 /bin/bash ./back.sh
 4874     1  4874  4874 /bin/bash ./fore.sh

###           ###

# ps -eo pid,ppid,pgid,sid,cmd |grep -E "back|fore"
 4871     1  4871  4871 /bin/bash ./back.sh
 4874     1  4874  4874 /bin/bash ./fore.sh

setsidを使用すると、現在ログインしているshellのjobsでback.shとfore.shが見つからないことがわかります.また、終了前にback.shとfore.shの親プロセスがinitであるため、再ログイン後にback.shとfore.shに変更はありません.
 
3.disownコマンドの使用
# ./fore.sh
^Z
[2]+  Stopped 
# jobs 
[1]-  Running                 ./back.sh &
[2]+  Stopped                 ./fore.sh
# ps -eo pid,ppid,pgid,sid,cmd |grep -E "back|fore"
 5395  5361  5395  5361 /bin/bash ./back.sh
 5396  5361  5396  5361 /bin/bash ./fore.sh
# disown -h %2
# disown -a %1
# jobs 
[2]+  Stopped                 ./fore.sh
# fg
./fore.sh

###           ###

# ps -eo pid,ppid,pgid,sid,cmd |grep -E "back|fore"
 5395  5361  5395  5361 /bin/bash ./back.sh

再登録後もfore.shが終了していることが判明し、SIGHUP信号が受信されたことが判明した.このことからdisownはバックグラウンドプロセスにのみ機能することが分かる.
 
4.  Catch SIGHUP信号
shellスクリプトの場合は、スクリプトに次の文を追加すればいいです.
# trap "" HUP

Cプログラムであればsignal関数を使ってSIGHUPをブロックすればよい.
signal(SIGHUP, SIG_IGN);

 
X.もちろん反対に、shellをexit終了時にSIGHUPをすべてのjobsに送信することもできます.具体的には以下のように設定します.
# shopt -s huponexit

 
テキストリンク:http://leehomjan.iteye.com/blog/2146739