仕事先が契約しているデータセンターのウェブサーバーがもう笑うしかないぐらい不安定。僅かなアクセスしか無いにも関わらず、気が付くとサーバーは落ちてるし、502、503、504のエラーが返るのも日常茶飯事。24時間通算してどれぐらい不具合が起きているのだろうか?と気になったので監視スクリプトを作ってみた。
監視スクリプトの仕様
- 監視スクリプトはターゲットのサーバーとは別の安定したサーバーに置く。
- 監視スクリプトはPHPで書いてcronで5分ごとに実行させる。
- ターゲットのサーバーから特定URLをGETするのに要した時間をログに書き出す。
ネットを調べるとpingコマンド利用のサーバー死活監視スクリプトが多数ヒットしたけど、僕が必要なのはブラウザにページが表示されるまでの体感時間なので、HTTPのGETのレスポンスタイムを計測するのが現実的かと。サーバーが完全に死んでいたらタイムアウトになるだろうし。
監視スクリプト
以下のようなスクリプトを作成した。HTTPリクエストの実行にはPEARのHTTP_Requestを利用。logsというサブディレクトリを作成しておくと、日付を名前にしたCSVファイルが自動生成されて、スクリプトが実行されるたびにログが追記される仕組み。監視するURLは複数指定可能にした。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
<?php error_reporting(E_ALL ^ E_NOTICE ^ E_DEPRECATED); set_include_path("." . PATH_SEPARATOR . "/xxx/xxx/pear/php" . PATH_SEPARATOR . get_include_path()); require_once "HTTP/Request.php"; function logging($message) { $file = dirname($_SERVER['SCRIPT_FILENAME']).'/logs/'.date('Ymd').'.csv'; $fh = fopen($file, 'a'); for ($i = 0; $i < 5; $i++) { // retry loop if (flock($fh, LOCK_EX)) { fwrite($fh, $message); fflush($fh); flock($fh, LOCK_UN); break; // success } sleep(1); // wait } fclose($fh); } function logging_succeess($ptime, $url, $code, $header) { $data = $ptime . "," . date('Y/m/d H:i:s') . "," . $code . "," . $url . "\n"; if ($code != 200) { $data .= print_r($header, true) . "\n"; } logging($data); } function logging_failed($ptime, $url) { $data = $ptime . "," . date('Y/m/d H:i:s') . "," . "FAILED," . $url . "\n"; logging($data); } $urls = array(); $urls[] = "http://www.site1.com/index.html"; $urls[] = "http://www.site2.com/index.php"; $urls[] = "http://www.site3.com/index.html"; $urls[] = "http://www.site4.com/index.php"; $urls[] = "http://www.site5.com/index.html"; $urls[] = "http://www.site6.com/index.php"; $option = array( "timeout" => "10", "allowRedirects" => true, "maxRedirects" => 3, ); foreach ($urls as $url) { $http = new HTTP_Request($url, $option); $http->addHeader("User-Agent", "SiteMon"); $http->addHeader("Referer", "http://www.myserver.com/"); $stime = microtime(true); $response = $http->sendRequest(); $etime = microtime(true); $ptime = $etime - $stime; if (!PEAR::isError($response)) { $code = $http->getResponseCode(); $header = $http->getResponseHeader(); $body = $http->getResponseBody(); $cookies = $http->getResponseCookies(); logging_succeess($ptime, $url, $code, $header); } else { logging_failed($ptime, $url); } } ?> |
実行例
以下にログファイルの抜粋を例として示す。各行先頭から処理時間(秒)、実行日時、ステータスコード、URLの順にカンマ区切りで記録される。ステータスが200以外のときはレスポンスヘッダの配列ダンプも追記される。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
0.17917799949646,2014/05/19 23:35:01,200,http://www.site1.com/index.html 0.41295695304871,2014/05/19 23:35:02,200,http://www.site2.com/index.php 0.073950052261353,2014/05/19 23:35:02,200,http://www.site3.com/index.html 15.073293924332,2014/05/19 23:35:03,408,http://www.site4.com/index.php Array ( [cache-control] => no-cache [connection] => close [content-type] => text/html ) 0.0778648853302,2014/05/19 23:35:32,503,http://www.site5.com/index.html Array ( [cache-control] => no-cache [connection] => close [content-type] => text/html ) 3.459300994873,2014/05/19 23:35:39,200,http://www.site6.com/index.php |