dポイントプレゼントキャンペーン実施中!

シェルスクリプトを作っています.
親プロセス(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

A 回答 (6件)

#4です。


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

#4です。


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

BBB.sh自身がやりたかった処理は、BBB.shは親がいなくなったら、自ら終了するとことです。

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

#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も終了します
    • good
    • 0
この回答へのお礼

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

お礼日時:2007/07/23 00:30

あ~, 「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 になったら (親が死んだということで) 終了させる, ということを言っているんじゃないかと思います.
    • good
    • 0
この回答へのお礼

ありがとうございます。
>SIGTERM をもらうと exit_AAA() に入るんですが, この中で kill したときに自分自身にも SIGTERM を送ります.

kill -- -$$だと自分もグループ内だから、またSIGTERMが送られてしまうということですか。考えが及びませんでした。

お礼日時:2007/07/19 20:14

環境が不明ですが、もしbashが使えるなら


PPID変数が使用可能です。これはこのシェルの親のプロセスIDを示しますので、BBB.shの親がいなくなったかどうかをこれで、判断できます。
    • good
    • 0
この回答へのお礼

bash使えます。
BBB.shのPIDをAAA.shで保存しておいて、AAA.shが終了したときに、BBB.shをkillするということでしょうか???確かにうまくいきそうです。

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

お礼日時:2007/07/18 21:28

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

    • good
    • 0
この回答へのお礼

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

お礼日時:2007/07/18 21:29

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!