シェルスクリプトを作っています.
親プロセス(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件)
- 最新から表示
- 回答順に表示
No.6
- 回答日時:
#4です。
>これだと、BBB.shでは親がいないかの監視しかできなくなってしまいますが
#4で書いたスクリプトをそのまま実行することは、想定していません。
ここで記述した主旨(親プロセスの監視及びそれがいない場合のシェルの終了)を、シェル内の関数にして、記述する等して、定期的に呼び出せば、親がいなくなった場合の対応ができるはずということを示す為に書きました。
もし、BBB.shの内容を提示していただければ、そのスクリプトを、親がいなくなった時、終了するように、書き換えることは可能です。
No.5
- 回答日時:
#4です。
>ちょっとまだ理解できていない点あるのですが、
>これだと、BBB.shでは親がいないかの監視しかできなくなってしまいますが、BBB.sh自身がやりたかった処理はさらに子プロセスを呼び出すということでしょうか???
BBB.sh自身がやりたかった処理は、BBB.shは親がいなくなったら、自ら終了するとことです。
そもそも、
「親プロセス(AAA.sh)から子プロセス(BBB.sh)を呼び出した状態で,AAA.shをkillすると,BBB.shのプロセスが終了しないまま,残ってしまうため」とあるように、親が死んだときに、BBB.shが終了しないのが問題であると理解しました。
従って、親が死んだことをBBB.shは定期的に監視し、親が死んだら自分も終了するようにすれば、解決できると判断しました。
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も終了します
ありがとうございます。
ちょっとまだ理解できていない点あるのですが、
これだと、BBB.shでは親がいないかの監視しかできなくなってしまいますが、BBB.sh自身がやりたかった処理はさらに子プロセスを呼び出すということでしょうか???
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 になったら (親が死んだということで) 終了させる, ということを言っているんじゃないかと思います.
ありがとうございます。
>SIGTERM をもらうと exit_AAA() に入るんですが, この中で kill したときに自分自身にも SIGTERM を送ります.
kill -- -$$だと自分もグループ内だから、またSIGTERMが送られてしまうということですか。考えが及びませんでした。
No.2
- 回答日時:
環境が不明ですが、もしbashが使えるなら
PPID変数が使用可能です。これはこのシェルの親のプロセスIDを示しますので、BBB.shの親がいなくなったかどうかをこれで、判断できます。
bash使えます。
BBB.shのPIDをAAA.shで保存しておいて、AAA.shが終了したときに、BBB.shをkillするということでしょうか???確かにうまくいきそうです。
しかし、なぜか今新しくサンプルを作り直して動作させてみたら、BBB.shが呼び出された後にAAA.shをkillしても,AAA.shのプロセスが残っているようにみえて、(ps ax)、上記の挙動と変わってしまいました(汗。。。
なんでだろう~♪
ただいま混乱中です。申し訳ありません。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) ¥マークを含むパスの処理について(マクロ、または関数) 2 2022/12/25 02:11
- Perl perl このテキストファイルを簡単に配列に入れるには? 2 2022/04/27 20:24
- UNIX・Linux Linuxについて質問です。 以下のhistoryの出力結果から、sedコマンドのファイル名tmp1 1 2023/02/03 20:11
- SQL Server ACCESSで3ファイルを結合して、表を作成するやり方を教えて下さい。 17 2022/08/15 20:34
- SQL Server ACCESSで複数テーブルを結合して、リストを作る方法を教えてください。 2 2022/08/12 19:32
- Excel(エクセル) Excel VBA 3 2023/04/22 10:46
- JavaScript jsonテキストデータの並び替えができるサービスを教えてください 2 2022/08/05 20:16
- SQL Server ACCESSで表が作りたく、そのためのSQL文や設定方法を教えてください。 1 2022/08/15 12:28
- その他(データベース) カラム上の重複を削除するクエリを教えてください 3 2022/04/12 14:11
- JavaScript 指定したパスが現URLに含まれていたら特定要素を削除するJavascriptのコードを教えてください 2 2023/04/27 17:58
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
バックグラウンドのプロセスの...
-
プロセスIDの取得方法について
-
explorer.exeが異様にメモリを食う
-
タスクマネージャーのプロセス...
-
プロセスIDからウィンドウハ...
-
プロセスのアタッチ・デタッチ...
-
CreateObjectで作成したExcelの...
-
怪しいプロセス教えてください。
-
他のコンピュータのプロセスを取得
-
ADOでアクセスのレコードに...
-
[C#]リモートコンピューターを...
-
C++のプログラムをバックグラウ...
-
Visual C++からpingを実行して...
-
プロセスハンドル or ウインド...
-
POSIX メッセージキュー作成時...
-
VBSからbat実行(WMI)して戻り値...
-
デバックにプロセスをアタッチ...
-
プロセスが実行中かどうか調べ...
-
C#でのbatファイル実行結果取得
-
WSH.Runで待機できません
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
バックグラウンドのプロセスの...
-
explorer.exeが異様にメモリを食う
-
タスクマネージャーのプロセス...
-
プロセスのアタッチ・デタッチ...
-
C#でのbatファイル実行結果取得
-
VB6.0 SHELLで起動...
-
ADOでアクセスのレコードに...
-
Windowsでのfork方法
-
非表示になったエクセルは?
-
共有メモリの同時アクセスにつ...
-
プロセスIDからウィンドウハ...
-
プロセスIDの取得方法について
-
C++のプログラムをバックグラウ...
-
C++でシェルを起動
-
Linuxでのスレッド間メッセージ...
-
OSPFでプロセスを分ける意義に...
-
怪しいプロセス教えてください。
-
Process.Startの戻り値を後で取得
-
SendMessageが失敗するときがある
-
ウィンドウのタイトルからプロ...
おすすめ情報