• 締切済み

デバッグ情報が画面から流れないようにするには。

膨大な量のデータを処理するプログラムを完成しました。私の環境は、ネット回線も細くパソコンも性能が低いこともあいまって、全ての処理を終えるのに2~3日かかるプログラムです。 それでも2~3日待てば処理が終わるのです。 やったー、と思ったまでは良いですけど、いざ動かしてみると、何やら警告が出ます。幸いまだデバッグ用の変数書き出しコードを削除していなかったので、だいたいバグが出たあたりが分かりました。処理結果を見てみると、確かに処理されたデータが壊れています。はて、何が原因かと、処理がその箇所を過ぎるあたりに注目しながらもう一度プログラムを動かしてみても、何故か今度は警告も出ないし、データを確認しても壊れていません。さっきのは一体なんだったのか。。。 とにかく再現できないことにはデバッグのしようもないので、プログラムの処理状況が分かりやすいように、変数の書き出しを削除せずに、あらためて今プログラムを動かしています。 プログラムを動かしてバグを再現するのは、デバッグの当然の手法でしょうが、変数を打ち出せば、なんせ2~3日かかるプログラムだけに、画面に大量の書き込みがなされて、警告が出ても流れてしまいます。そうかといって2~3日、ずっと画面を眺めているわけにもいきません。 変数をファイルに書き出すようにしても、警告はディスプレイに出ますから、するとどの時点で警告が出たのか、そのときの変数の値がどうだったのか、ファイルとディスプレイを時系列的に照らし合わせることが出来なければ、今ひとつ判断に困ります。 perl bugtuki.pl > test.txt のようにすれば警告もファイルに書き出すことが出来ますが、2~3日待たなければ、ファイルを開くことができません。 警告をファイルに書き出して、そのファイルをプログラムの処理中に見る方法などあるでしょうか。そのほか、この手の状況で、迅速にデバッグ情報を把握する方法がございましたらご教授ください。 一応DOS窓の画面バッファの高さを最大限にはしました。 言語はPerl 5.14.2。デバッグツールとしてActive Perl社のPerl Div Kit 8.2.1を使っています。

みんなの回答

  • N60-BASIC
  • ベストアンサー率80% (17/21)
回答No.3

ご自分で作られているプログラムとのことですので、(自分で書いた)警告を標準出力ではなく標準エラー出力に出すように一本化するのが最善だと思います。 現在printなどでデバッグ用表示を行っているところを、warnに置き換えてみてはどうでしょうか。 warnは、引数文字列の末尾に改行がついていない場合、スクリプト行番号も表示してくれますので、よりデバッグしやすくなります。 warn("hoge\n"); # hoge と警告 warn("hoge"); # hoge at スクリプト名 line 1234 と警告 スクリプト処理では、最終出力結果(実行目的と言うべき?)のみを標準出力に出し、進捗状況の表示や警告、エラーなどは標準エラー出力に出すのが一般的であり、大原則です。 例えば「あらかじめ指定されたファイルへの出力」が目的のスクリプトであれば、正常終了する限り標準出力には何も表示しないのが普通です。(もちろんエラーは標準エラー出力に吐かれます) あと、デバッグを容易にするためのアドバイスとして、いくつかご参考まで。 ●大掛かりな処理を行っているとのことですが、問題をできるだけ局所化することはできませんか? 例えば ・入力ファイルのサイズが大きい場合に、可能であればファイルをあらかじめ分割してテストしてみる ・膨大なループを回さなければいけない場合、ループの回数を減らしてテストしてみる などです。 あるいは、処理のアルゴリズム自体に問題があるために実行が遅い場合もあります。 実際にやっている処理や条件(入出力のサイズなど)をここで質問して、最適化の方法がないか意見を求めてみるのもいいと思います。プログラム系の質問サイトでは、「わかりません!作ってください」よりも「よりうまく動かす方法ありませんか?」のほうが、回答者のモチベーションが上がることが多いです。 ●Perl4の文法で書いていませんか? Perl5では、スクリプト先頭に use strict; use warnings; を書いた上で、利用する全ての変数について使う前にmyで変数宣言を行うことで、変数名のタイプミスをコンパイルエラーにしたり、未定義値の予期せぬ利用に対して警告を出してくれたりします。 また、スクリプトのブロック { ~ } 内やループ定義文(while, for, ...)でmyを宣言することで、ブロックの外に影響を及ぼさない変数を作ることができます。名前の競合などを気にしながら大量のグローバル変数を作る必要がなくなります。大規模なスクリプトであるほど、効果は絶大です。 ●どうにも処理を簡略化できず、結局いつ起こるかわからないエラーを待たなければならない場合・・ 先ほどのwarnを自作ルーチンに置き換えて、例えばエラーが起きるたびに自分宛てにエラー内容をメールで飛ばす、なんてことも検討しなければいけないかもしれません。 正常終了時にもメールを飛ばせるなら、より便利になるでしょう。 ●実行時に失敗する可能性のありそうなところでは、しっかりチェックと例外処理を入れる 私の経験的には、一番時間がかかる類の処理は、例えば「大量のログを正規表現でマッチさせて、結果を加工して出力する」といったものです。が、入力ファイルのフォーマットがあいまいな仕様だったりすると、試行錯誤を繰り返さなければいけない場合があります。その際、正規表現のマッチが成功しているかどうか等、戻り値を調べてやることを怠ると、予期せぬ結果につながってしまいます。

すると、全ての回答が全文表示されます。
  • N60-BASIC
  • ベストアンサー率80% (17/21)
回答No.2

OSがWindowsだと仮定して、 perl bugtuki.pl >test.txt 2>debug.txt とすれば、標準エラー出力をファイルに書き出すことができます。 書き出し中のファイルをリアルタイムに監視するには、他の回答者さんが挙げたリソースキットのtail.exeを使うか、あるいはフリーウェアのWintailあたりが有用かと思います。

すると、全ての回答が全文表示されます。
  • t-okura
  • ベストアンサー率75% (253/335)
回答No.1

> perl bugtuki.pl > test.txt > のようにすれば警告もファイルに書き出すことが出来ますが、 > 2~3日待たなければ、ファイルを開くことができません。 Windows のリソースキットに tail コマンドが入っているので、それを使うとよいでしょう。 tail -f test.txt で test.txt に出力中のデータを表示することができます。 確かめていませんが notepad でも出力中のファイルを開くことができたように思います。

参考URL:
http://www.atmarkit.co.jp/fwin2k/win2ktips/423tail/tail.html
makoji
質問者

補足

ご教授ありがとうございます。お返事が遅くなり申し訳ありません。 この補足はN60-BASICさんとt-okuraさんのお二人へのものです。 どうも私の勘違いで、単純に  perl bugtuki.pl > test.txt とやっただけでは、正常な出力はファイルに入れることが出来ますが、エラー出力はファイルに入りません。 N60-BASICさんが教えてくださったように  perl bugtuki.pl >test.txt 2>debug.txt とやると、確かに標準エラー出力もファイルに入れることが出来るようになりますが、しかし正常な出力とエラー出力が別のファイルに分かれてしまって、二つのファイルの書き込みのタイミングの整合が取れません。 どうにかして同じファイルに入れることはできないものでしょうか。 ただ一度ファイルに落とすと、まだプログラムが動いている間でも、ブラウザでファイルを閲覧することができました。少しタイミングが遅れますが、今回の用途は何時間かおきに変なエラーが出ていないかチェックを入れるだけなので、このタイミングのずれは気にしなくていいと思います。 あるいは、出力がDOS窓から流れて消えない程度のところで、窓を切り替えたら如何かと思ったりしますが、単純にcmd.exeを呼び出すだけでは、今開いている窓を一掃してしまうだけなので、どうしようかと迷っています。 何か良い方法がございますでしょうか。

すると、全ての回答が全文表示されます。

関連するQ&A