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

rsyncの終了ステータスによってその後の処理を切り替えています.

<src>
rsync -auz --delete $SDIR $DDIR

if [ $? -eq 0 ]; then

 END=`date '+%Y-%m-%d-%H-%M-%S'`
 echo "$END $1 end" >> /home/hoge/log
else

 echo "ERROR! exit status $?" >> /home/hoge/log
fi
</src>

rsyncが正常終了すればlogファイルに時間を記入して,
正常終了しなかったら,終了ステータスを記入します.

もし,rsyncが正常終了したにも関わらず,ちょうどif [ $? -eq 0 ]; thenに入るまえに
他のコマンドが異常終了したら変数$?の値が変わると思います.

かなり気にしすぎかもしれませんが,rsyncだけの終了ステータスに注目するにはどうしたらいいでしょうか?

よろしくお願いします.

A 回答 (8件)

>crontabでシェルを動かしているときにkillをしてもkillコマンドの終了ステータスは入ることなくrsyncの終了ステータスをちゃんと受け取れるという理解でよろしいでしょうか?



まず他の方が書いているように、$? はそのシェルプロセスのローカル変数なので、別のプロセス(上記だと、killコマンドを投入した対話型シェルのプロセス)の影響を受けることはありません。

rsync が実行途中でkillされた場合、rsyncの終了ステータス $? は、128+(killのシグナル番号) になります。killのシグナル番号はデフォルトだと15なので、143 ですね。kill -9 とかすると、137 になります。

正確には、「rsyncは15番のシグナルでkillされた」ということがrsyncを呼び出したシェルプロセス(bashとかshとか)に返るので、シェルが+128して、$? にセットして通常の終了(プログラムが自分で狩猟ステータスを指定して終了した)場合と区別できるようにしてます。
あと、126と127もシェルによって予約されたステータスです。
つまり、
・ ?$ が 0~125 → プログラムが終了コードを指定して終了した(Cだとexit(cc);とか return cc;とか)
・ ?$ が 126 → コマンドが存在するが実行に失敗した(実行権限なしなど)
・ ?$ が 127 → コマンドが存在しない(command not found)
・ ?$ が 128 → このケースはたぶん無いはず
・ ?$ が 129~ → コマンドが実行中にシグナル番号($?-128)でkillされた
    • good
    • 1

No7さん。



やっと、ちゃんと理解してくれている人が投稿してくれたようですね。

質問者に代わってお礼を。

ちなみに man で確認をと以前かきましたが、man の検索結果の一例です。正確には、対処のマシンでman or ヘルプを見てください(設置していない場合もあるが、デフォルトは設置されている)。

http://linux.die.net/man/1/rsync
(この「Exit Values」項目が戻り値です。

これがあなたが使用しているOSで、そのバージョンで対象のコマンドなら、そのページでいいですが、

正確にOS名やバージョンの記載がないのでわかりません)

http://linux.die.net/man/5/rsyncd.conf
(基本的には、この設定ファイルでコントロールする。理解しておいた方がいいでしょう)

http://www.infoscience.co.jp/technical/rsync/rsy …
第3者による解説サイトですね

http://www.infoscience.co.jp/technical/rsync/ind …
いろいろあるのです)

それと、以前にも記載しましたが、終了ステータスは、あくまでコマンドの作成者が予期した範囲での数字です。予期していない場合は、

ただしい値が返っているとは言えないのです。なので、私としての見解は

「$?の値の信頼性を問うなら、メッセージやログを保存し、その違いで分岐する」

が、信頼性を向上させる鍵です。上記の「infoscience.co.jp」にも、それに則した似たようなサンプルが掲載されています。
    • good
    • 1

> rsyncが正常終了したにも関わらず,ちょうどif [ $? -eq 0 ]; thenに入るまえに


> 他のコマンドが異常終了したら変数$?の値が変わると思います

これを心配するのだったら

if rsync -auz --delete $SDIR $DDIR ; then
 END=`date '+%Y-%m-%d-%H-%M-%S'`
 echo "$END $1 end" >> /home/hoge/log
else
 echo "ERROR! exit status $?" >> /home/hoge/log
fi

とすれば、rsyncの終了ステータスそのもので判定するので、少なくとも、rsync成功したときにERRORとログが残ることは無い。
    • good
    • 0

もう一つおまけ。



>コマンドの仕様により、0だったり、1だったり

ちょうどいいサンプルがありましたので、

http://shellscript.sunone.me/exit_status.html

input_check.shのスクリプトですね。exprの計算が成功し0となるはずが、計算結果が0になる。exprの仕様により結果が0の場合、終了ステータスは異常を示す1が返る。

実行は成功しているにもかかわらず、結果の内容によりステータスを変える。

これは、良くある事なので、それぞれのコマンドで違うのである。


また ”「 rm -f 」の終了ステータス”

の項目も理解しておいて欲しい。

何がいいたいか理解していただけましたでしょうか?

文献としては古いので、かならずしもその通りになるとは限りませんが、先人の苦悩を拾うことが重要です。

その文献の初めにありますが

「各コマンドにより異なるが、一般的にはコマンド成功時には「0」が、失敗時には「1」が設定される。」

と言うこと。各コマンドにより違うのである。

あなたの疑問は

input_check.shのスクリプトを同じシェル内で、同時実行してみたり、別シェル(ウインドウ)で同時実行してみたり、crontabで同時刻にやってみて、どうなるか試したらいかかですか?

例えば、違う結果になるようにして、別シェルで同時実行したらどうなるか?
    • good
    • 0

>crontabでシェルを動かしているときにkillをしてもkillコマンドの終了ステータスは入ることなくrsyncの終了ステータスをちゃんと受け取れるという理解でよろしいでしょうか




コードに「<src>」があることが気になるが、あなたが言っているのはシェルスクリプトとしての実行でいいのですよね。

何かのサービスの子プロセスから実行されると言う事でしょうか? つまり、シェルのエミュレーション機能があるサービスで、シェルを模倣して実行される?

そうでないのなら、$? などと言う変数は、シェルの実行単位で有効であり、スコープはローカル変数となります。

つまり、シェルスクリプトが2つ実行されれば、それぞの変数に影響を与える事はありません。ただし、B-Shellであれば、Exportコマンドでグローバル変数となり、実行しているシェル(コマンドツールなどのGUIツール内)では、存在すれば上書きされます。

別のシェルで、それぞれ別に実行すれば、いくらExportコマンドでグローバルにしても、それぞれの変数が上書きなど、影響を与える事はありません。

と言うことは、

「crontabでシェルを動かしているときにkillをしてもkillコマンドの終了ステータスは入ることなくrsyncの終了ステータスをちゃんと受け取れるという理解でよろしいでしょうか」

は、別々のシェルで実行されることになるので、CrontabでKillされても、$?の変数が、そのCrontabのデーモンの成功、失敗を拾うことなく、

rsyncの仕様にしたがって、killされた時の終了ステータスを実行しているシェルから$?を通して受け取ります。

このことを、No3で語ったつもりだったのですが・・・



問題は、rsyncの仕様で、他のプロセスからKillを実行されて終了しても、正常終了として0を返すのか、それとも不明として3以上を返すのか、私は把握していません。

コマンドの仕様により、0だったり、1だったり2だったり、時には255なんて場合もあります。

それはマニュアルに記載されているし(MAN)、実際試せば分かる事です。


なので、私は、終了メッセージや、ログを拾って、分岐させることを、特に業務用ではお勧めします。


あなたが理解しなければならないのは、変数のスコープと、シェルスクリプトの実行の仕組みです。

/bin/shのプロセスの実行単位でローカル、グローバル変数がコントロールできます。


聞くよりも、実際に試してみたらいかかでしょうか?
    • good
    • 0

対策を書くのを忘れていました。



UNIX系のコマンドだと、終了ステータスを拾うという手段は、最初に考える事なんですが、私は、いろんな場合を考え、よく2段がまえで処理を切り分けています。

これはスクリプトだけでなく、C++、Java、HTML系のスクリプトにおいても。


と言うのも、対象処理がハング状態やクラッシュした時(ステータス的には正常終了と出る時がある<=なぜか言えば、それを終了させるプロセスがあるので、対象のプロセスを正常に終了させたと言うこと)など、正確なステータスを拾うことが困難です。

そこで、UNIX系のコマンドだと、エラー出力、標準出力など切り分けて、終了メッセージやログなどを出力する仕組みがそなわっているのがほとんどです。

それらを解析して、終了ステータスと組み合わせて、実行させます。

Oracleなどの業務系のDBや、それに合わせたアプリだと、不思議なクラッシュやハング状態があるものです。

そういったものに、ダブルチェックで異常事態を確実に把握するのには、とても役に立ちます。

1回作ってしまえば、後はコピーするだけなので、使い回しができますよ。
    • good
    • 0
この回答へのお礼

#2の方にお礼を書かせていただきました.

少々確認したいこともありますので,#2のお礼にも目を通していただけると幸です.

お礼日時:2011/08/30 12:29

質問の趣旨からいえば、No1でも同じだと思うのだが・・・・



>ちょうどif [ $? -eq 0 ]; thenに入るまえに

そもそも、その考えが違っています。

>他のコマンドが異常終了したら変

その他のコマンドは 「if [ $? -eq 0 ];」 の前に記載されていませんよね。そのスクリプトの前述でバックグランド処理をするスクリプトを書いているか、バックグランド処理されるコマンドを実行していない限り、その部分が評価する対象は直前のシェル(実行単位)から渡される、終了ステータスのみです。

他の実行単位でのコマンドの終了ステータスが入る事は、ありえません。できるのでしたら、プロセス間通信で悩む必要はなくなります。(スクリプトレベルでも簡単にできることになる)
    • good
    • 0
この回答へのお礼

ありがとうございます.

このスクリプトでバックグラウンド処理はしていませんが,
たとえば,crontabで定期的に実行しているときに
root権限をもったユーザがkillコマンドでプロセスを切れたとしたら
変数$?はどうかわるのか気になって質問させていただきました.

解答から,私の懸案事項は他の実行単位での終了ステータスは入ることはないから,
crontabでシェルを動かしているときにkillをしてもkillコマンドの終了ステータスは入ることなくrsyncの終了ステータスをちゃんと受け取れるという理解でよろしいでしょうか?

お礼日時:2011/08/30 12:28

LOG=/home/hoge/log


rsync -auz --delete $SDIR $DDIR
result_rsync=$?
if [ ${result_rsync} -eq 0 ]; then
echo `date '+%Y-%m-%d-%H-%M-%S'` $1 end >>$LOG
else
echo ERROR! exit status ${result_rsync} >>$LOG
fi
    • good
    • 0

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