Cygwin なんでも掲示板

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


スレッド

└◇3313:
Re[2]:perlからの戻り値 [zxcv] 02/08 00:34

 └◇3314:Re[3]:perlからの戻り値 [OZ] 02/08
  ├◇3315:Re[4]:perlからの戻り値 [zxcv] 02/09


3313● Re[2]:perlからの戻り値[ zxcv ] 2007 02/08 00:34
# 私も細かなことはかなり忘れてしまっています。 歯切れの良いことが書けずにすみません。

> perlの処理を行う前にsql*plusを使用しているのですが、そこでエラーが起こった場合、trapで処理しているのです。そこでシグナルを使用しているのですが・・。

どうも、やりたいことが見えてこないのですが。

以下の2点が解る様にご説明願えませんか?

1 「他人が書いたソフトがそうなってる」のか「ご自分で決めたこと」なのかの区別。

2 登場するプロセスには何があるのか? シグナルの発生と捕捉はどのプロセスでの事なのか? (Shellスクリプトから起動したコマンドやスクリプトは全て別プロセスって言うのは理解されてすよね?)


> 初歩的な質問かもしれませんが、シェルから呼び出したスクリプトなどで戻り値として数字を返すと、それはシグナルとして認識されてしまうのでしょうか?

スクリプトの種類(bash か perl か)によって細かな違いはあるでしょうが、 exit はそのスクリプトを終了させるための手段です。 exit を発行すると「プロセスの終了」という捕捉可能なシグナルが発生する場合はあるかも知れませんが、そのシグナルは exit 起因とは限りません。 もちろん、 「exit 13」で13番シグナルは発生しません。

P.sh という bash スクリプトが内部で C.sh を呼んだとします。 C.sh が 「exit 13」で終了したとき、P.sh でその「13」を知る普通の方法は、前回も書いた $?という変数の参照です。

試してませんが、P.sh で、C.sh の呼出前に 「set -e」を実行しておけば、 C.sh が 0 以外で exit したときに P.sh も即座に終了するんではないかと思います。 その「P.shの終了」は、P.sh 中に書いた trap で捕捉できるかも知れませんが、C.sh の終了コードを知る方法は、ちょっと解らないです。

# シグナルは結構難解です。 勉強のためにあえてチャレンジするなら別ですが、普通はシグナルを使わずに済む方法を探す方が良いケースが多いと思いますよ。
スレッド一覧


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