https://www.youtube.com/watch?v=VV7b7fs4VI8
1 comment | 0 points | by WazanovaNews 約2時間前 edited
パッケージ(apt, yum, gem等)レポジトリのホスティングサービスであるPackageCloudを開発している、James Golickの講演です。
パフォーマンスの高いハイクオリティなソフトウェアをデプロイしたければ、あらゆるレベルでバグ修正ができるようになること。
まず、エピソードとして紹介しているのが、友人の会社のサイトが落ちて、あいにく、その会社のエンジニアが出払ってしまっていて、どうにかしてほしいと助けを求められたときのこと。
- ソースコードを見たことない。
- システムの構成を知らない。
- phpは詳しくない。
- SSHでアクセスできる情報だけはある。
という状況の中で、
- phpはおそらくApacheプロセスを実行しているだろうからということで、pidファイルを確認。
- 次に、straceコマンドを使って、プログラムが実行したシステムコールをチェック。システムコールは、ユーザランドのプログラムとOS間のインターフェースを提供していて、ファイルを書込んだり、ソケットを扱ったり、メモリをアロケートしたりと様々なことに役に立つ。
- straceのアウトプットは、ファンクション名 / 引数 / 返り値で構成されている。Rubyなどのデバッグでも役立つし、詳細なドキュメントも用意されているので、参照されたし。
- アウトプットの量が膨大でも、読み方のコツとしては必ず最後から順に追うこと。「500 Internal Server Err」などを見つけたら、その後にある詳細内訳はおそらく役に立たないから、エラーの原因があると思われる、その前のアウトプットを調べる。比較的近い位置に原因に関する情報があることが多い。
- この場合は、まず
ope(“/var/www/db.in.php”, O_RDONLY) = -1 ENOENT (No such file or directory)というエラーメッセージを見つけた。そのすぐ前のところにopen(“/var/www/index.php”, O_RDONLY) = 13という成功したシステムコードがある。grepで確認したところ、indexはdb.in.phpをincludeしていているので、パーミッションの設定が悪いと思いきや、ファイルは確かに存在していた。しかし、db.inc.phpというタイプミスだとわかった。
というかたちで対処した。
次に、顧客が、パッケージクラウドレポジトリを最新のUbuntuでインストールしようとしたときのこと。
- “Ign”(= ignore)に次いでクリティカルなファイルに該当するURLを表示するメッセージが続き、アプリが何も見つけられなかったか、もしくはリクエストが失敗したことがわかる。パッケージインデックスがワークしていない。
- 前回はエラー後の既存のプロセスを分析したが、今回は違って、straceコマンドの傘下でプロセスを実行し、数メガのデータを生成。
- データの最後から順に追って、「Ign + ローカルバーチャルマシンのIPアドレス + ディストリビューション + アプリが見つけられないファイル」の箇所を発見。
- 次に、その手前に「… 400 URI Failure…s3.amazon.com…Bad header line…」という箇所があり。Amazon S3が400エラーを返しているという不思議な情報。同じS3のURLで確認したところ、問題なく 200 OK が返ってくる。
- ここから先は思ったより大変。例えば、Red Hatのディストリビューションは相当なパッチがされているので、パッケージに表示されているバージョン番号のソースからはかなり内容が変わっている可能性がある。「apt-get source パッケージ名」で実際のソースを自分のシステムのホームディレクトリに持ってくるのがよい。
- 解決には何らかの手がかりが必要。ソースコードにおそらくハードコーディングされてるであろうstringを探してみる。今回は、「Bad header line」という表現がソースのどこかで見つけられると推定した。その仮説は正しくて、多言語化のファイルとC++のファイルで、「Bad header line」というメッセージが定義されていた。
- C++をよく知らなくても、ここは頑張ってよくコードを睨んで想像してみる。(スライド: PCで全画面表示すると読めます。)HTTPパーサーが一般的なものよりもかなり厳しめなのがわかる。良くないとする型のヘッダーを探して「Bad header line」のエラーをだしている。結論としては、「> Content-Type:」と定義してたのでエラーになっており、「Content-type: plain-text」とすることで解決。
振返ってみての学びは、
- 自分がわかってるはずと思うことは全部忘れること。
- システムの他のレイヤでのデータも調べること。(こちらのスライドにレイヤの詳細あり。)
- 見るべき正しいソースコードの場所を特定すること。
- ソースコードの中でgrepできるハードコーディングされたstringを見つけること。
- ソースコードを合点がいくまでよく見ること。
- 壊れてるところは全て直す。
#php #c++ #障害対応