※記事内に商品プロモーションを含む場合があります
今まで、サーバの監視と言う事をやってませんでした。
サーバのデータを記録しておく事で、何で落ちたかが
分かりやすくなります。
また、異常が発生した時に通知が来る用にすれば
サーバが反応しない時間を少しでも短く出来ると思い
サーバモニタリンク・通知用スクリプトをPHPでつくりました。
この前はZabbixと言うソフトを使っていました。
モニタリンクと異常通知用PHPスクリプト
動作・ロギング
cronを使って10秒に1回スクリプトを実行。
通常cronは最低でも1分に1回ですが、1分に1回にして
for i in `seq 0 10 59`;do (sleep ${i};php スクリプト) & done; >/dev/null 2>/dev/null
の用にcronに設定すれば10秒に1回実行されます。
取得するデータは以下の通り
- ロードアベレージ1分
- ロードアベレージ5分
- ロードアベレージ15分
- メモリ使用率
- スワップ使用率
- httpdプロセス数
Apacheのhttpdプロセス数はzabbixでは取れなかったデータ。
プロセス数とメモリの状況を見る事でApacheの状況をより把握出来ます。
メモリとスワップを使用率にしたのは
バイト単位だと、最大と使用の2項目必要になりますが
使用率なら1項目で済みます。
1番は項目を減らす事での容量削減です。
このデータと時間をcsv形式にして保存します。
保存は最新のデータが上になる様にしました。
こうする事で表示用スクリプトで開く時に先頭を読むだけで
現在のステータスを確認出来ます。
ログは日付.logに保存されます。
スクリプトには明日のデータを消去する機能もあるので
簡易的なログローテーション機能となっています。
明日の日付のログを消す事で先月のログと今月のログが
混在してしまうのを防いでいます。
動作・通知
サーバのロードアベレージ1分が3を超えたらau携帯(iPhone)に
メールを送信する用に設定しました。
ロードアベレージが3以上を維持してると10秒に1回iPhoneに通知が
送信されるので、さすがにそれはやり過ぎ。
対策としてメールを送信したらロックファイルを作って
ロックファイルがある時はメール送信をしない様にしました。
そのままだと、いざという時にメールが送信されないので
ロードアベレージ1分が0.5を下回ったらロックファイルを削除します。
マルチコアでのロードアベレージ
シングルコアの場合、ロードアベレージが1以上の場合
実行待ちが発生している状態と言われます。
マルチコアの場合イロイロと説はありますが
1×コア数で良いと思います。
このVPSは3コアなのでロードアベレージ1分が3になったら
通知する様に設定しました。
多少低い気はしますが、
3ぐらいであればサーバがまだ反応するのですぐ気付いた場合は
すぐ対処出来るのでまぁ良いかなと思っています。
メール通知に分厚いauの壁
テスト環境は自宅サーバーなのでOP25Bが効いて
メール送信は出来ません。
メール送信はVPSで試しましたが一向にメールが届きません。
試しにG-Mailにしたら一発で届きました。
返送先のメールアドレスを指定してもダメ。
spfレコードを設定してもダメ。
2~3時間ぐらい悩みましたが
結局は、自分のiPhoneでauの迷惑メールフィルターに
アクセスしホワイトリストに送信元のメールアドレスを設定しました。
設定後試したら、すぐに届きました。
コード
<?php
/*
サーバモニタリンク&ロギンクスクリプトby @eaxjp
eax’s monitering bot
システムステータスのロギングとロードアベレージが3以上になった場合通知するスクリプトです。
(C)eax Version .1.5- 20150816 https://b.eax.jp/
*/
//日時取得
$now = getdate();
//HTTPプロセス数取得
$http_p = exec(‘ps aux|grep httpd|wc -l’);
$http_p = $http_p – 1;
//ロードアベレージ取得
$la = sys_getloadavg();
$la1 = $la[0];
$la5 = $la[1];
$la15 = $la[2];
//メモリ使用率
$memory_result = explode(“\n”, `free -m`);
$memory_pattern = “#^-/\+ buffers/cache: +([0-9]+) +([0-9]+)$#”;
preg_match($memory_pattern, $memory_result[2], $memory_info);
$mem_r = round(( $memory_info[1] / intval($memory_info[1] + $memory_info[2]) ) * 100,1);
//スワップ使用率
$memory_result = explode(“\n”, `free -m`);
$memory_pattern = “#^Swap: +([0-9]+) +([0-9]+) +([0-9]+)$#”;
preg_match($memory_pattern, $memory_result[3], $memory_info);
$swap_r = round(( $memory_info[2] / $memory_info[1] ) * 100,1);
//通知 ロードアベレージ
//ロードアベレージ1分が3を超えたらメール送信、ロックファイル作成
//0.5以下になればロックファイルを削除。これにより連続でメール送信されるのを防ぐ
if($la1 >= 3 and file_exists(dirname(__FILE__).”/mail_send.lock”) == false){
mb_language(“Japanese”);
mb_internal_encoding(“UTF-8”);
$body = <<< EOD
ロードアベレージ(1分)が3以上に上昇しています。
* * 現在の状況 * *
現在の時刻:{$now[‘hours’]}時{$now[‘minutes’]}分{$now[‘seconds’]}秒
Apacheのプロセス数:{$http_p}
ロードアベレージ 1min:{$la1}
ロードアベレージ 5min:{$la5}
ロードアベレージ 15min:{$la15}
メモリ使用率:{$mem_r}
スワップ使用率:{$swap_r}
EOD;
mb_send_mail(“送り先”, “サーバ異常通知”, $body ,”From: 送り元”, “-f 送り元”);
$fp = fopen(dirname(__FILE__).”/mail_send.lock”, “w”);
fwrite($fp, ‘1’);
fclose($fp);
}
if($la1< 0.5){
if (file_exists(dirname(__FILE__).”/mail_send.lock”)) {
unlink(dirname(__FILE__).”/mail_send.lock”);
}
}
//ログ保存 CSV形式にて保存、日付.logで/log/に格納される
$sd = array($now[‘hours’], $now[‘minutes’],$now[‘seconds’],$la1,$la5,$la15,$http_p,$mem_r,$swap_r);
//時間・分・秒・LA1・LA5・LA15・httpdプロセス数・メモリ使用率・スワップ使用率
//ログデータの作成 out=$csv_line
$fp = fopen(‘php://memory’, ‘r+’);
fputcsv($fp, $sd);
rewind($fp);
$csv_line = stream_get_contents($fp);
fclose($fp);
$fn = dirname(__FILE__).”/log/”.$now[‘mday’].”.log”;
//ファイルが存在しない場合はエラーを防ぐ為、空ファイルを作る
if (file_exists($fn) == false) {
$fp = fopen($fn, “w+”);
fclose($fp);
}
//ログファイルを読み込んで、最新データが先頭になる様に保存
$content=file_get_contents($fn);
$content= $csv_line.$content;
file_put_contents($fn,$content);
//明日のログ削除 先月と今月のログが混在するのを防ぐ
$asu = date(“j”, strtotime(“+1 day”));
$fn = dirname(__FILE__).”/log/”.$asu.”.log”;
if (file_exists($fn)) {
unlink($fn);
}
あとがき
コードのご利用は自己責任でお願いします。
ロギングしたデータを表示するスクリプトも作ったので
こちらは別記事で書きます。