戦闘でPHPを安定化する-Webサーバーがドロップする理由と理由

PHPでのWebプロジェクトの安定性について責任を負います。 負荷は絶えず増大し、機能が追加され、顧客は満足しています。 ある晴れた日、神秘的なエラーが現れ始めます...



サーバーソフトウェアエラー



...プログラマは修正方法を知らない サーバーソフトウェアは、たとえば、一連のapache-PHPを「破壊」し、クライアントは要求に応じて定期的なメンテナンスに関するページを受け取ります。 Web開発者はunix / linuxでのCプログラミングの深い知識を持っていないことが多く、システム管理者は残念ながらシステムにbashより深く潜らないことがよくあります。 本当のハードコア:-)



サーバースクリプトの不安定な動作



多くの場合、Webプロジェクトの特定のページがおかしくなり始めます。 たとえば、完了するのに15分かかり、彼らがしていることを見つけるのは簡単ではありません。 このトピックに関する以前の投稿で 、戦闘サーバー上のPHPスクリプトが何を行うかを決定する方法の1つについて説明しましたが、より強力なツールが必要であると感じています。



実際には、よく似たクラスのサーバーソフトウェアエラーが発生するプロジェクトに遭遇しますが、チームは何をすべきかを常に把握しているわけではありません。 セグメンテーション障害メッセージはApacheログに頻繁に表示され、クライアントはエラーページを取得し、システム管理者と一緒にWeb開発者が頭を悩ませ、さまざまなバージョンのPHP / Apache /プリコンパイラで遊んで、さまざまなオプションでソースからPHPを何度も収集しますバグについて書いてください。これらはPHPのバグではなく、コードなど、無限に続くことが証明されています...



記事では、PHPが戦闘サーバーで崩れた理由をすばやく簡単に見つけて、それを排除する方法を教えたいと思います-UNIXのCシステムプログラミングの美しい世界に飛び込むことなく:-)欲望とコーヒー1杯が必要になります。







Webサーバーのエラーログを確認します



Apacheエラーログに次のようなメッセージが表示される場合は、次の記事を参照してください。

[Mon Oct 01 12:32:09 2012] [notice] child pid 27120 exit signal Segmentation fault (11)









この場合、スクリプトではなくプロセス自体がクラッシュしたため、PHPエラーログで詳細な情報を探すことは役に立ちません。 事前にnginxの定期的なメンテナンスに関する素晴らしいページを作成していない場合、クライアントには禁欲的なエラー「50 *」が表示されます。



誰かに顔を見せたいのですが、誰に? :-)破壊的な決定から注意をそらすために、理論を思い出します。



シグナルとは何ですか? これは、たとえば、オペレーティングシステムがプロセスにそれが間違っていることを伝えるために使用するツールです:-)数学の法則に違反し、... 0で除算するか、強制アクションによってスタックオーバーフローが発生します。 この場合、11という数字と「SIGSEGV」という名前のシグナルが表示されます。 シグナルのリストは、「kill -l」を実行することで表示できます。

...

11) SIGSEGV

...









SIGSEGVなどの一部の信号は傍受できないため、Apache-PHPプロセスは試行なしでカーネルによって容赦なく強制終了されます。 彼を傍受することが正確に判明しました-それは可能ですが、ソースに登る必要があります:-)



そして、なぜ彼らはそれを殺したのですか?



では、apache-PHPプロセスが強制終了された理由を見つけましょう。 これを行うには、kill :-)またはcoredumpの時点でプロセスメモリのダンプを構成します。 はい、はい-これまで、廃止された50年という用語が使用されてきました。これは、磁気コアからのデータの保存を意味します。 次回プロセスがオペレーティングシステムによって強制終了されるとすぐに、ファイルがカーネルによって作成されます 。場所とその名前を設定できます 。 コンソールにいる場合は、「man 5 core」と入力するだけです。



たとえば、次のようにファイルをパパに入れることができます。

echo "/tmp/httpd-core.%p"> / proc / sys / kernel / core_pattern



何も設定されていない場合、システムはプロセスの作業ディレクトリに「core。#Process_number#」というファイルを作成します。



apache-PHPプロセスに書き込み許可があることを確認してください。



それだけではありません。 デフォルトでは、ほとんどの場合、コアダンプファイルの生成はシステムで無効になっています。 Webサーバーの起動スクリプトの先頭に行を挿入することで有効にできます。

ulimit - unlimited





または、設定を永続的にするには、ファイル「/etc/security/limits.conf」を編集します。 そこに挿入できます:

apache - core -1







ファイル形式の詳細は「man limits.conf」です。



ただし、Apacheのコアダンプファイル用のフォルダーを設定するまで、 何も機能しませんでした ( "/etc/httpd/conf/httpd.conf")。

CoreDumpDirectory /tmp









次に、Apacheを再起動します。

service httpd restart









テスト中です。 プロセスを手動で強制終了します。

ps aux | grep httpd

...

キル-12 12345



「/ var / log / httpd / error_log」を確認します。

[Mon Oct 01 16:12:08 2012] [notice] child pid 22596 exit signal Segmentation fault (11), possible coredump in /tmp









「/ tmp」には、「/ tmp / httpd-core.22596」などの名前のファイルがあります。



終了したプロセスのメモリダンプを取得する方法を学びました。 現在、プロセスが自然に終了するのを待っています。



犯罪現場で-コアダンプの解釈



PHPがデバッグシンボル(コンパイル時のgccの--enable-debug、-gキー)なしで構築されている場合、多くの有用な情報が失われることを知っておくことが重要です。 ただし、このオプションがなくてもソースからPHPをコンパイルし、ソースが近くにある場合-分析にはこれで十分かもしれません。

デバッグビルドがパフォーマンスとプロセスによって消費されるメモリフットプリントに影響を与えるという非常に一般的な誤解がまだあります。 影響はありませんが、実行可能ファイルのサイズは増加するだけです。 したがって、ビルドをデバッグせずにエラーの原因を特定できない場合は、システム管理者にデバッグシンボルを使用してPHPモジュールをビルドするよう依頼してください。



コアダンプを開く方法は? もちろん、古くて「非常に親切な」ユーティリティ-gdbは 、元々はフリーソフトウェア運動のリチャードストールマンの大使によって作成されました。

デバッガの動作を理解するのにそれほど時間はかかりません。 数時間で最も面白い教科書の1つを吸収するか、システム管理者にこれを依頼することができます;-)



通常、次のようにコアダンプを開きます。

gdb path_to_ executable_file_web server path_to_coredump



unixのすべての自尊心のあるC開発者は、このデバッガの使用方法を確かに知っています。おそらく毎日それを行いますが、残念ながら、彼らはあなたのチームにいないかもしれません。 そしてもう1つ不快なものがあります...



GDBでのPHPデバッグ-ブラックマジック



実際、バイトコードにコンパイルされたPHPスクリプトは... Cプログラムではありません;-)かなりではありますが、

Zendエンジンの内部を理解します。そして、 すぐに理解できます。 つまり、トレースで実行関数の最後の呼び出しを見つけ、スタックのこのフレームに移動してローカル変数(op_array)を調べ、Zendエンジンのグローバル変数を調べる必要があります。

 (gdb) frame 3 #3 0x080f1cc4 in execute (op_array=0x816c670) at ./zend_execute.c:1605 (gdb) print (char *)(executor_globals.function_state_ptr->function)->common.function_name $14 = 0x80fa6fa "pg_result_error" (gdb) print (char *)executor_globals.active_op_array->function_name $15 = 0x816cfc4 "result_error" (gdb) print (char *)executor_globals.active_op_array->filename $16 = 0x816afbc "/home/yohgaki/php/DEV/segfault.php"
      
      







op_arrayと混同される可能性があるため、この構造のようなルックアップコマンドは便利です。

 (gdb) ptype op_array type = struct _zend_op_array { zend_uchar type; char *function_name; zend_class_entry *scope; zend_uint fn_flags; union _zend_function *prototype; zend_uint num_args; zend_uint required_num_args; zend_arg_info *arg_info; zend_bool pass_rest_by_reference; unsigned char return_reference; zend_uint *refcount; zend_op *opcodes; zend_uint last; zend_uint size; zend_compiled_variable *vars; int last_var; int size_var; zend_uint T; zend_brk_cont_element *brk_cont_array; zend_uint last_brk_cont; zend_uint current_brk_cont; zend_try_catch_element *try_catch_array; int last_try_catch; HashTable *static_variables; zend_op *start_op; int backpatch_count; zend_bool done_pass_two; zend_bool uses_this; char *filename; zend_uint line_start; zend_uint line_end; char *doc_comment; zend_uint doc_comment_len; void *reserved[4]; } *
      
      







デバッグプロセスは、スタックのフレーム(「フレームN」)間のウォーク、「execute」関数の各呼び出しへの切り替え、ローカル引数(「print name」、「ptype name」)の検査で構成されます。 フレーム番号が低いほど、あなたは深くなります。 PHPの拡張機能にアクセスして、エラーが発生した場所と理由を確認すると便利な場合があります(少なくとも理由を理解してください)。



 (gdb) frame ## (gdb) print op_array.function_name $1 = 0x2aaab7ca0c10 "myFunction" (gdb) print op_array.filename $2 = 0x2aaab7ca0c20 "/var/www/file.php"
      
      







などなど...



コーヒーで窒息した場合:-)、コマンド「frame#N#」を使用してコールスタックのフレームを切り替えると、この構造の特定の要素をすべて見ることができます-PHP関数が呼び出されたPHPファイルに間違いなく設定できることを覚えておいてください彼女が呼んだ機能など -そして、「セグメンテーションフォールト」またはプロセスを強制終了したその他のエラーの原因に到達します。 そして、プログラマーにその理由を説明すると、彼らはそれを修正します! すぐに、そして楽観的でなければなりません-永遠に。



エラーの一般的な原因



コアダンプファイルの参照を開始(またはシステム管理者に割り当て)すると、エラーをグループに分類する方法をすぐに学習できます。

1)PHP拡張の問題。 この場合、拡張機能を無効にするか、その設定で遊んでみてください。 あなたは確かに問題がそれにあることを知っています、問題は小さいです。

2)再帰の問題、スタック。 エラーが発生し、pcreなどのライブラリ関数が再帰に入り、自身を2万回呼び出すエラーが発生する場合があります。 ライブラリ設定を構成するか、遅延している場合は、プロセスに大きなスタックを追加できます( "/etc/init.d/httpd"):



ulimit -s「値をさらに設定」



また、現在の値は、コマンド「ulimit -a」で表示できます(ulimitを実行してから、「ulimit」を探します)。

3)PHPコアの問題-ここでは、PHP開発者に書き込む必要があります:-)



一般に、エラーの原因の範囲は大幅に削減されます。 これが必要なものです。



実行中のプロセスのデバッグ



それだけではありません。 コアダンプを取得できない場合は、実行中のプロセスに接続して、それを見て回ることができます。 プロセス内にいる間、その実行は一時停止されます(「ps aux | grep apache | grep 'T'」-トレース状態になります)。 あなたが彼を去るとき、彼は再び処刑され続けます。 次のように接続できます。

gdb -pプロセスID



まとめ



この記事では、サーバーソフトウェアエラーを「正しく準備」する方法、Apache-PHPデバッグビルドを作成する方法、コアダンプファイルを作成する方法、およびシンボリックデバッガーを使用して正しく解釈する方法を学びました。 また、コアダンプファイルから、特定のPHPファイルとエラーの原因となった関数を見つけることができることも学びました。



これで、マネージャーのためのチェックリストを作成して、Web開発者もシステム管理者も把握できない謎のサーバーエラーを処理できます。



  1. サーバー(sysadmin)でコアダンプファイルのコレクションを有効にします
  2. 必要に応じて、デバッグシンボルを使用してapache-PHPを再構築します(sysadmin)
  3. gdb(週末で学習)を使用して、エラーの原因を調査します(Web開発者のシステム管理者)
  4. 設定を変更する、発生頻度を減らすなどの対策を講じます。設定の変更、ソフトウェアの更新、バグトラッカーへの書き込み、PHP拡張機能の無効化など。




結論として、私はBitrix24クラウドサービスに全員を招待します。 このサービスでは、記事で説明されているすべてのテクノロジーを効果的に使用します。



皆さんの幸運とWebプロジェクトの安定した仕事に!



All Articles