• 締切済み

シェルで親プロセス終了時に子プロセスも終了させるには?

シェルスクリプトを作っています. 親プロセス(AAA.sh)から子プロセス(BBB.sh)を呼び出した状態で,AAA.shをkillすると,BBB.shのプロセスが終了しないまま,残ってしまうため, http://oshiete1.goo.ne.jp/qa1968135.html を参考にkill -- -$$で同じプロセスグループのものが終了するように作ったのですが,BBB.shが呼び出される前にAAA.shをkillすると,プログラムが暴走してしまいます. どうすれば暴走せずに,親子ともども終了させることができるでしょうか??? *** AAA.sh *** #!/bin/sh func exit_AAA(){ kill -- -$$ exit 1 } trap "exit_AAA" HUP INT QUIT TERM echo "call BBB??(y/n)" read num ./BBB.sh *** BBB.sh *** #!/bin/sh echo "exit BBB?(y/n)>" read num

みんなの回答

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.6

#4です。 >これだと、BBB.shでは親がいないかの監視しかできなくなってしまいますが #4で書いたスクリプトをそのまま実行することは、想定していません。 ここで記述した主旨(親プロセスの監視及びそれがいない場合のシェルの終了)を、シェル内の関数にして、記述する等して、定期的に呼び出せば、親がいなくなった場合の対応ができるはずということを示す為に書きました。 もし、BBB.shの内容を提示していただければ、そのスクリプトを、親がいなくなった時、終了するように、書き換えることは可能です。

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.5

#4です。 >ちょっとまだ理解できていない点あるのですが、 >これだと、BBB.shでは親がいないかの監視しかできなくなってしまいますが、BBB.sh自身がやりたかった処理はさらに子プロセスを呼び出すということでしょうか??? BBB.sh自身がやりたかった処理は、BBB.shは親がいなくなったら、自ら終了するとことです。 そもそも、 「親プロセス(AAA.sh)から子プロセス(BBB.sh)を呼び出した状態で,AAA.shをkillすると,BBB.shのプロセスが終了しないまま,残ってしまうため」とあるように、親が死んだときに、BBB.shが終了しないのが問題であると理解しました。 従って、親が死んだことをBBB.shは定期的に監視し、親が死んだら自分も終了するようにすれば、解決できると判断しました。

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.4

#2です。 >ちなみに #2 の「PPID を~」というのは, 多分 BBB.sh の方で PPID の変化を見張っておき, 1 になったら (親が死んだということで) 終了させる, ということを言っているんじゃないかと思います. まさにその通りです。 bashが使えるというので、上記の方法を試しました。 実行結果は、AAA.shが死んでも、PPIDは1になりませんでした。(いったんPPIDがセットされるとその値は、親が死んでも変わりませんでした) ですので、この方法は却下します。 PPIDを使うと言った手前、このままでは、無責任ですので、別の方法を提案します。 1案 PPIDの存在(親プロセスの存在)をPSコマンドで監視し、PPIDに該当するプロセスが存在しなければ、親が死んだと判断する。 2案 psコマンドを発行し、自プロセスの親のプロセスIDが1なら、親が死んだと判定する。 以下、1案のスクリプトです。 AAA.shの内容 BBB.shを起動 -------------- #! /bin/sh echo "moto=$$" ./BBB.sh & sleep 30 --------------- BBB.shの内容 親が死ねば即終了 そうでなければ120秒間監視を繰り返す -------------- #! /bin/sh COUNT=0 echo "oya=$PPID" while : ; do RESP=`ps -p $PPID | grep $PPID` echo "RESP=$RESP" if [ "$RESP" = "" ];then echo "親がいないので終了" exit 9 fi sleep 2 COUNT=`expr $COUNT + 1` if [ $COUNT -gt 60 ] ; then echo "TIMEOUT" exit 10 fi done ----------------------------------- 上記スクリプトを実行し、AAA.shのプロセスをkillすると、 BBB.shも終了します

BIGMON
質問者

お礼

ありがとうございます。 ちょっとまだ理解できていない点あるのですが、 これだと、BBB.shでは親がいないかの監視しかできなくなってしまいますが、BBB.sh自身がやりたかった処理はさらに子プロセスを呼び出すということでしょうか???

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

あ~, 「BBB.sh を実行する直前に trap~」というのは, trap をかけてから BBB.sh を実行するまでの間で問題が起きるんだろうから, 危険な時間をなるべく減らそうという方策です. 問題ないなら, これが最も簡単でしょう. でちょっと手元でいじっていたんですが, kill の行を間違えたときに無限ループっぽい感じがしました. どういうことかというと, SIGTERM をもらうと exit_AAA() に入るんですが, この中で kill したときに自分自身にも SIGTERM を送ります. すると, trap の指示に従って再度 exit_AAA() に入ります. これをくりかえして, 最後に死んでいるような感じです. ということで「exit_AAA() の中で, kill する前に trap し直す」ということを考えてみました. つまり, function exit_AAA() { trap '' TERM KILL kill -- -$$ exit 1 } のようにしたらどうだろうか, ってことです. ちなみに #2 の「PPID を~」というのは, 多分 BBB.sh の方で PPID の変化を見張っておき, 1 になったら (親が死んだということで) 終了させる, ということを言っているんじゃないかと思います.

BIGMON
質問者

お礼

ありがとうございます。 >SIGTERM をもらうと exit_AAA() に入るんですが, この中で kill したときに自分自身にも SIGTERM を送ります. kill -- -$$だと自分もグループ内だから、またSIGTERMが送られてしまうということですか。考えが及びませんでした。

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.2

環境が不明ですが、もしbashが使えるなら PPID変数が使用可能です。これはこのシェルの親のプロセスIDを示しますので、BBB.shの親がいなくなったかどうかをこれで、判断できます。

BIGMON
質問者

お礼

bash使えます。 BBB.shのPIDをAAA.shで保存しておいて、AAA.shが終了したときに、BBB.shをkillするということでしょうか???確かにうまくいきそうです。 しかし、なぜか今新しくサンプルを作り直して動作させてみたら、BBB.shが呼び出された後にAAA.shをkillしても,AAA.shのプロセスが残っているようにみえて、(ps ax)、上記の挙動と変わってしまいました(汗。。。 なんでだろう~♪ ただいま混乱中です。申し訳ありません。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

BBB.sh を実行する直前に trap を設定すれば, 危険はかなり減ると思う.

BIGMON
質問者

お礼

直前のほうがよいのですか。知りませんでした。ありがとうございます。