Cygwin なんでも掲示板

一覧最新記事過去一覧 | 検索FAQアンテナHOME
(新規投稿・発言はできません)


スレッド

└◇3314:
Re[3]:perlからの戻り値 [OZ] 02/08 10:46

 ├◇3315:Re[4]:perlからの戻り値 [zxcv] 02/09


3314● Re[3]:perlからの戻り値[ OZ ] 2007 02/08 10:46
返信ありがとうございます。
言葉が足りず申し訳ありません。
シェルは全てbashです。
「他人の書いたソフトがそうなっている」パターンです。

現在
A.sh(親シェル)
から
A_child.sh(子シェル)
を呼び出し、

A_child.sh内で
loader.shを呼び出しています。

loader.shはSQL*LOADERを呼び出す処理を、行っています。

loader.shはSQL*LOADERの処理の成否に応じて
成功なら、exit 0
失敗なら、exit 1
で終了します。

A_child.sh内にはtrapが記述してあり、
loader.shが、exit 1 で終了した場合、trap内の処理が実行されます。

今回、A_child.shに対して、
loader.shを呼び出した後にperlを呼び出す処理を追加する
という作業を行うことになったのですが、
perl内でexit 1を行うと、これまでの流れから考えれば当然なのですが、trapされてしまいます。

私が行いたいことは
例えばperl内での処理結果が3種類ある場合、
それぞれの結果に応じて(どの結果でも正常終了として扱いたい)
exit 1,exit 2,exit 3
と戻り値を変えて、
A_child.shで$?を使用しその戻り値を受け取り、
それを利用してA_child.sh内のその後の処理をif分岐させたい、ということです。
ちなみにperlはA_child.shから直接呼び出しています。

今回質問したいのは2点あります。

1、perlの最後にexit 0を記述すると、trapされずに処理が終了するが
exit 1など、0以外を記述するとtrapされ処理が終了してしまう。
どうすればperlからの「戻り値」をtrapさせずに$?で受け取ることができるか?

2、trapとは「シグナル」を捕捉するコマンド、bashやperl内のexit ** は「戻り値」を返すコマンド、だと認識しています。しかしtrapで捕捉されてしまう、ということは
exit ** で返しているのは「シグナル」なのか?それとも「戻り値」と「シグナル」は同じ意味なのか?先ほどの書き込みを読ませていただいた限り、やはり「戻り値」と「シグナル」は別物でexit ** は「戻り値」を返していると思うのですが・・。

長文になり申し訳ありません。
もしわかりましたらよろしくお願いいたします。
スレッド一覧


3315● Re[4]:perlからの戻り値[ zxcv ] 2007 02/09 00:03
やはり、前回も書いた 「set -e」の線が一番怪しいと思います。

試しに、A_child.sh の perl 呼出の直前に「set +e」という 1行を挿入して実行してみてください。 perl が 0以外で exit しても trap されなければ、質問1 は一旦解決ですね。

問題は、その修正が新たなバグを作り込んでいないかどうかです。 そのソフトが、バグや故障に起因して誤動作すると人様に迷惑をかける様な性質のソフトであれば、そのまま完了にするのはとても危険です。

perl 呼出の直後に 「set -e」の 1行を入れるだけで良いかも知れませんが、緻密なシグナル設計がされたソフトなら全体をしっかり見た方が安全です。 perl スクリプトで予想外のエラーが起った時にどの様なエラー処理が適切かも含めて考えた方が良いと思います。


実は、「set +e」を使わない方法もあります。 exit は常に 0 として、A_child.sh に返す値は STDOUT を使用する方法です。 (perl スクリプトがすでに STDOUT を使用してるなら、STDERR に切り替える等して STDOUT を返値専用にしてくださいね)

この方法を使用するには、まず perl 中の 「exit 2;」とかを「print 2; exit 0;」とかに変更してください。

次に A_child.sh の perl 呼出の変更です。 perl 呼出が 「perl script.pl」、「perl directry/script.pl」、「directry/script/pl」、「script.pl」のいずれの形式であってもその全体を `(バック・シングル・クォート)で囲んで以下の様にしてください。

sts=`もとのPerl呼出`

こうすれば、perl が STDOUT に出力した内容は $sts という Shell変数で参照できます。 stsという変数名は、すでに使われてたら変えてください。


最後に質問2 ですが、プロセスの終了コードはあくまでも別物です。 しかし、今回の様に因果関係があって連動しているかの様に見える場合もあります。

bash は、自分の子プロセス(今回の場合 A_child.sh や perl)の異常終了(0 以外での exit)を検知して自らを終了させる機能があります。 その有効・無効を制御するのが「set -e」と「set +e」です。

bash に限らない一般論として、プロセスが終了する時には SIGTERM(だったかな?)というシグナルが発生します。 それを A_child.sh は trap で拾っているのでしょう。

「exit 1」は親プロセスにシグナルを発生させる遠因であって、シグナルそのものでは無いことがお解り頂けますね?
スレッド一覧

早田のホームページへ
CGIROOM