[解決済み] Perl CGI スクリプトのトラブルシューティングはどのようにすればよいですか?
質問
動作しないPerlスクリプトがあるのですが、どのように問題を絞り込んでいけばいいのかわかりません。どうしたらよいでしょうか。
注:質問を追加しているのは、私の非常に長い回答をStackoverflowに追加したいからです。私は他の回答でそれに外部リンクし続け、それはここにあるに値します。もし何か追加することがあれば、私の答えを編集することを恥ずかしがらないでください。
どのように解決するのですか?
この回答は、Perl CGI スクリプトの問題を解決するための一般的なフレームワークとして意図されています。 Perl CGI スクリプトの問題を解決するための一般的な枠組みを意図しており、元々は Perlmonks に Perl CGI スクリプトのトラブルシューティング . これは、すべての問題に対する完全なガイドではありません。 また、バグ潰しのチュートリアルでもありません。 これは は、20年以上にわたってCGIスクリプトをデバッグしてきた私の経験の集大成に過ぎないのです。 このページは、いろいろな家にあったようですが、私はその存在を忘れてしまったようです。 だから、StackOverflowに追加しています。あなたは コメントや提案があれば [email protected]。コミュニティWikiでもありますが、あまり無茶をしないようにしましょう :)
問題を発見するためにPerlの組み込み機能を使っていますか?
警告をオンにして、コードの疑わしい部分についてPerlが警告を出すようにします。これはコマンドラインから
-w
スイッチを使ってコマンドラインから行うことができますので、コードを変更したり、すべてのファイルにプラグマを追加したりする必要はありません。
% perl -w program.pl
ただし、疑わしいコードは常に強制的に
warnings
を追加することで、常に疑わしいコードを消去するように強制する必要があります。
use warnings;
短い警告メッセージ以上の情報が必要な場合は
diagnostics
プラグマを使ってより多くの情報を得るか、あるいは
perldiag
のドキュメントを参照してください。
use diagnostics;
最初に有効なCGIヘッダを出力しましたか?
サーバーは、CGI スクリプトからの最初の出力が CGI ヘッダであることを期待しています。 典型的には、それは次のような単純なものでしょう。
print "Content-type: text/plain\n\n";
あるいは
CGI.pm
とその派生物です。
print header()
. 一部のサーバは、エラー出力に敏感です (
STDERR
) が標準出力より先に表示されることに敏感なサーバもあります (on
STDOUT
).
ブラウザにエラーを送信してみる
この行を追加する
use CGI::Carp 'fatalsToBrowser';
をスクリプトに追加します。また、これはコンパイルエラーをブラウザウィンドウに送信します。余分な情報はセキュリティリスクとなりうるので、本番環境に移行する前に必ず削除してください。
エラーログには何が書かれていましたか?
サーバーはエラーログを保持しています (少なくとも、そうあるべきです)。 サーバーやスクリプトからのエラー出力はそこに表示されるはずです。 はそこに表示されます。 エラーログを見つけて、何が書いてあるか見てください。 ログファイルの標準的な場所があるわけではありません。 ログファイルの標準的な場所はありません。 サーバーの設定を見るか、サーバーの管理者に聞いてください。 管理者に聞いてみてください。 また、次のようなツールを使うこともできます。 CGI::Carp といったツールを使って、独自のログファイルを保持することもできます。
スクリプトのパーミッションはどうなっていますか?
もし、"Permission denied"や"Method not implemented"のようなエラーが表示された場合は、スクリプトが実装されていないことが考えられます。
のようなエラーが表示された場合、それはおそらく、スクリプトが Web サーバーのユーザーによって読み取りおよび実行できないことを意味します。
Web サーバーのユーザーによって読み取りおよび実行可能ではないことを意味します。 Unixの種類
の場合、モードを755に変更することをお勧めします。
chmod 755 filename
. 決してモードを777に設定しないでください!
を使用していますか?
use strict
?
Perlでは、最初に変数を使用する際に、自動的に変数が作成されることを覚えておいてください。
を作成します。 これは機能ですが、時々
バグを引き起こすことがあります。 プラグマ
use strict
はその種の
を見つけるのに役立ちます。 慣れるまでは面倒ですが、しばらくするとプログラミングが格段に上達し
プログラミングがかなり上達しますし
自由にいろいろなミスをすることができるようになります。
スクリプトはコンパイルできますか?
コンパイルエラーを確認するには
-c
スイッチを使用します。 最初に報告されたエラーに集中する。 リンスする。
を繰り返してください。本当におかしなエラーが出る場合は、スクリプトの行末が正しいかどうか
スクリプトの行末が正しいかどうか確認してください。 もし、あなたが
バイナリモードで FTP したり、CVS からチェックアウトしたり、あるいは他の方法で
行末の変換を行わない場合、ウェブサーバはあなたのスクリプトを1つの大きな行と見なすかもしれません。
スクリプトが1つの大きな行として認識される可能性があります。 PerlスクリプトをASCII
モードで転送します。
スクリプトは安全でない依存関係に対して文句を言っていますか?
スクリプトが安全でない依存関係を訴えている場合、あなたはおそらく
を使用している可能性があります。
-T
スイッチを使ってテイントモードをオンにしていると思われます。
これは、チェックされていないデータをシェルに渡さないようにするためのもので、良いことです。もし
が文句を言っているのなら、それは私たちがより安全なスクリプトを書くのを助けるために仕事をしているのです。プログラム外から来た
プログラムの外から来たデータ (つまり環境) は、汚染されていると見なされます。
は汚染されているとみなされます。 環境変数
PATH
と
LD_LIBRARY_PATH
は特に厄介です。 これらを安全な値に設定する必要があります。
に設定するか、私が推奨するように、完全に設定を解除する必要があります。 いずれにせよ、絶対パスを使用する必要があります。
パスを使うべきです。 汚染チェックで何か問題が発生した場合。
データが汚染されていないことを確認してください。 参照
パールセック
のマニュアルページを参照してください。
コマンドラインから実行するとどうなるのでしょうか?
コマンドラインから実行したときに、スクリプトは期待通りの結果を出力しますか。
を出力しますか? ヘッダーが最初に出力され、その後に
空白行が続きますか? 次のことを忘れないでください。
STDERR
とマージされる可能性があることを忘れないでください。
STDOUT
にマージされることがあります。
バッファリングにより、順番が乱れて表示されることがあります。 をオンにします。
を設定することで、Perl の自動フラッシュ機能を有効にします。
$|
を
を真値に設定します。典型的な例としては
$|++;
で
CGI プログラムで見られる。 一度設定すると、すべての印刷と書き込みは
バッファリングされるのではなく、即座に出力されます。
これは各ファイルハンドルに対して設定する必要があります。 使用方法
select
を使ってください。
を使って、デフォルトのファイルハンドルを変更します。
$|++; #sets $| for STDOUT
$old_handle = select( STDERR ); #change to STDERR
$|++; #sets $| for STDERR
select( $old_handle ); #change back to STDOUT
どちらにしても、最初に出力されるのはCGIヘッダです。 であり、その後に空白行が続きます。
CGIのような環境でコマンドラインから実行するとどうなるのでしょうか?
ウェブサーバ環境は通常、コマンドライン環境よりもはるかに制限され コマンドライン環境よりもはるかに限定されており、リクエストに関する余分な の情報を持っています。 スクリプトがコマンドラインからうまく実行される場合 コマンドラインから問題なく実行できるのであれば、ウェブサーバ環境をシミュレートしてみてはいかがでしょうか。 環境をシミュレートしてみてください。 問題が発生する場合は、環境に問題があると考えられます。 環境の問題です。
これらの変数をアンセットまたは削除してください
-
PATH
-
LD_LIBRARY_PATH
-
全て
ORACLE_*
変数
これらの変数を設定する
-
REQUEST_METHOD
(設定されたGET
,HEAD
またはPOST
を含む) -
SERVER_PORT
(通常80に設定) -
REMOTE_USER
(保護されたアクセスを行っている場合)
最近のバージョンの
CGI.pm
( > 2.75 ) には
-debug
フラグが必要です。
フラグが必要です。
に追加する必要があるかもしれません。
CGI.pm
インポートに追加する必要があるかもしれません。
use CGI qw(-debug)
を使用していますか?
die()
または
warn
?
これらの関数は
STDERR
に出力されます。
に出力します。 また、CGIヘッダも出力されません。 同じ機能を
のようなパッケージで同じ機能を得ることができます。
CGI::Carp
ブラウザのキャッシュをクリアするとどうなるのでしょうか?
スクリプトが正しいことを行っていると思い込んでいて 手動でリクエストを実行したときに正しい出力が得られた場合 出力される場合、ブラウザが原因である可能性があります。 キャッシュをクリアし をクリアし、キャッシュサイズをゼロに設定してテストしてください。 覚えておいてください。 ブラウザの中には本当に愚かなものがあり、あなたが再読み込みするように指示しても を指示しても、実際には新しいコンテンツを再読み込みしないブラウザもあることを忘れないでください。 これは これは、URLパスが同じでもコンテンツが変わる場合に特によく起こります。 が同じで、コンテンツが変更される場合 (例: 動的な画像) に特によく見られます。
スクリプトはあなたが考えている場所にありますか?
スクリプトのファイルシステムのパスは、必ずしもスクリプトの URL のパスと スクリプトの URL パスに直接関係するものではありません。 正しいディレクトリがあることを 正しいディレクトリがあるかどうかを確認してください。 短いテストスクリプトを書いてでも、正しいディレクトリがあることを確認してください。 さらに、次のことを確認してください。 正しいファイルを変更していますか? もし、変更しても 変更しても効果が見られない場合は、別のファイルを変更している可能性があります。 あるいは、間違った場所にファイルをアップロードしている可能性があります。 (ちなみに、これは私が最もよく起こすトラブルです。 ;)
あなたは
CGI.pm
またはその派生物を使用していますか?
もしあなたの問題が CGI の入力の解析に関連していて、かつ
のような広くテストされたモジュールを使っていないのであれば
CGI.pm
,
CGI::Request
,
CGI::Simple
または
CGI::Lite
を使用する場合は、モジュールを使用して、人生をやり直すことができます。
CGI.pm
には
cgi-lib.pl
互換モードがあり、古い CGI パーサの実装による入力の
互換モードがあり、古い CGI パーサーの実装による入力の問題を解決するのに役立ちます。
絶対パスを使用しましたか?
外部コマンドを実行する際に
system
で外部コマンドを実行している場合は、外部プログラムの絶対パスを指定する必要があります。
を使用して外部コマンドを実行する場合、外部プログラムへの絶対パスを使用する必要があります。
何を実行しているのかが正確に分かるだけでなく、セキュリティ上の問題も回避できま
セキュリティ上の問題も回避できます。 ファイルを読み書きするために
ファイルを読み書きのために開いている場合は、絶対パスを使用してください。
CGI スクリプトはカレントディレクトリについて、あなたとは異なる考えを持っているかもしれません。
ディレクトリについて、あなたと異なる考えを持つかもしれません。 別の方法として
明示的な
chdir()
を使用して正しい場所に置くこともできます。
戻り値を確認しましたか?
ほとんどのPerl関数は、動作したかどうかを教えてくれます。
を設定し
$!
をセットします。 あなたは
戻り値を調べて
$!
を調べましたか?あなたは
$@
を使用していた場合
eval
?
使用しているPerlのバージョンは?
Perl の最新の安定バージョンは 5.28 です (あるいはそうでないかどうかは、これが最後に編集された時間による)。 古いバージョンを使っていませんか? Perlのバージョンが違えば、警告の考え方も違うかもしれません。
どの Web サーバーを使用していますか?
同じ状況でも、サーバーが異なると動作が異なることがあります。 同じ状況でも、サーバーによって動作が異なることがあります。 同じサーバー製品でも、構成が異なると動作が異なる場合があります。 異なる構成で異なる動作をすることがあります。このような情報を をできるだけ多く含めるようにしてください。
サーバーのドキュメントを確認しましたか?
真面目な CGI プログラマは、サーバについてできるだけ多くのことを知るべきです。 サーバーの特徴や動作だけでなく、ローカルの設定も含めて。 と動作だけでなく、ローカルの設定も含みます。サーバーの のドキュメントは、商用製品を使用している場合、利用できないかもしれません。 もし、あなたが商用製品を使っているのであれば そうでない場合は の文書がサーバーにあるはずです。 そうでない場合は を探します。
のアーカイブを検索しましたか?
comp.infosystems.www.authoring.cgi
?
これは便利なものでしたが、良い投稿者たちは皆、死んでしまったか、消えてしまったのです。
誰かがあなたの問題を以前に抱えていた可能性があります。 そして、誰か (おそらく私) がこのニュースグループでそれに答えています。 ニュースグループで回答しているはずです。このニュースグループは全盛期を過ぎましたが、過去から集めた知恵が役に立つことがあります。
短いテスト スクリプトで問題を再現できますか。
大規模なシステムでは、多くのことが起こっているため、バグを追跡することが困難な場合があります。 を追跡するのは難しいかもしれません。 できるだけ短いスクリプトで問題 動作を再現するようにしましょう。 問題を知ること を知ることが修正の大部分である。 これは確かに時間がかかるかもしれませんが、あなたはまだ問題を発見しておらず まだ問題が見つかっておらず、選択肢がないのです。)
映画を見に行くことにしたのですか?
真面目な話です。 私たちは時々、問題に没頭するあまりに 知覚の狭窄(トンネルビジョン)になってしまうことがあります。 休憩を取る。 Duke Nukem、Quake、Doom、Halo、COD]で悪者をやっつけると、問題に再び取り組むために必要な新鮮な視点を与えてくれるかもしれません。 で悪者をやっつけると、問題に再アプローチするために必要な新鮮な視点が得られるかもしれません。
あなたは問題を声に出しましたか?
もう一度真剣に。 声に出して問題を説明することで 自分なりの答えを導き出すことがあります。 ペンギン(のぬいぐるみ)に話しかけるのは 同僚が聞いてくれないから。 もし、あなたがこのことに興味があるのなら 本格的なデバッグツールとして興味をお持ちの方は(今まで問題を発見できなかった方にはお勧めします。 をお読みになることをお勧めします。 コンピュータ・プログラミングの心理学 コンピュータ プログラミングの心理学 .
関連
-
[解決済み] CGI(Common Gateway Interface)とは何ですか?
-
[解決済み] Perlからロケール設定の警告を修正する方法
-
[解決済み] 最近のPerlはなぜデフォルトでUTF-8を避けるのですか?
-
[解決済み] CPANにすべての依存関係をインストールするように指示するにはどうしたらいいですか?
-
[解決済み] PerlからUTF-8を出力するにはどうしたらいいですか?
-
[解決済み] なぜPerl 5の関数プロトタイプはダメなのか?
-
[解決済み] Perl のフラグ -pe, -pi, -p, -w, -d, -i, -t?
-
[解決済み] Perlのハッシュのキーを反復処理する最も安全な方法は何ですか?
-
[解決済み] なぜstrictとwarningを使うのか?
-
[解決済み] Perlで文字列が空かどうかをチェックする適切な方法は何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] CPANにすべての依存関係をインストールするように指示するにはどうしたらいいですか?
-
[解決済み] PerlからUTF-8を出力するにはどうしたらいいですか?
-
[解決済み] Perlでファイルが存在するかどうかを確認するにはどうすればよいですか?
-
[解決済み] なぜPerl 5の関数プロトタイプはダメなのか?
-
[解決済み] Perl のフラグ -pe, -pi, -p, -w, -d, -i, -t?
-
[解決済み] Perlのハッシュのキーを反復処理する最も安全な方法は何ですか?
-
[解決済み] なぜstrictとwarningを使うのか?
-
[解決済み] Perlで文字列が空かどうかをチェックする適切な方法は何ですか?
-
[解決済み] Perlでハッシュを結合するには?