PHPとシェルスクリプトでサーバー監視 CRONを使った自動監視システム
サーバーのパフォーマンス監視は、運用の安定性を確保するために重要です。
PHPの shell_exec 関数を活用し、top や vmstat + awk を組み合わせることで、CPU使用率やゾンビプロセスの状態を取得できます。
本記事では、これらのコマンドを使った監視スクリプトを紹介し、CRON に設定することで定期的な監視を自動化する方法を詳しく解説します。
5分ごとに監視スクリプトを実行するCRONの設定例 :
crontab -e # 以下の行を追加 */5 * * * * /usr/bin/php /path/monitor.php > /dev/null 2>&1
「monitor.php」ファイル
<?php
//メールFrom
$from="webmaster@hoge.jp";
//メールTo
$to="webmaster@hoge.jp";
//件名
$subject="サーバー警告";
//閾値の設定(例)
$thresh=[
"process"=>[
"zombie"=>10 //ゾンビプロセス数が10個以上
],
"cpu"=>[
"ussy"=>95, //5秒平均のCPU使用率が95%以上
"wa"=>80 //IO待機時間の割合が80%以上
],
];
//警告メッセージ
$warning=[
"process"=>[
"zombie"=>"ゾンビプロセス数が %d で閾値(".$thresh["process"]["zombie"].")以上です。\r\n"
],
"cpu"=>[
"ussy" =>"5秒平均のCPU使用率が %f で閾値(".$thresh["cpu"]["ussy"].")以上です。\r\n",
"wa" =>"IO待機時間の割合が %f で閾値(".$thresh["cpu"]["wa"].")以上です。\r\n".
"ディスクIO又は通信IOが増加しています。\r\n"
],
];
$command='top -b -n 1|head -n 4';
$ret_top=shell_exec($command);
$ret_top=explode(",", preg_replace('/\r\n|\n/', ',', $ret_top));
$command='vmstat 1 5 | awk \'NR>2 {us+=$13; sy+=$14; id+=$15; wa+=$16} END {print us/5, ",", sy/5, ",", id/5, ",", wa/5}\'';
$ret_vmstat=shell_exec($command);
$ret_vmstat=explode(",", $ret_vmstat);
$val=[
"process"=>[
"running" => intval(preg_replace('/[^\d]/','',$ret_top[7])),
"sleeping" => intval(preg_replace('/[^\d]/','',$ret_top[8])),
"stopped" => intval(preg_replace('/[^\d]/','',$ret_top[9])),
"zombie" => intval(preg_replace('/[^\d]/','',$ret_top[10])),
],
"memory"=>[
"free" => intval(preg_replace('/[^\d]/','',$ret_top[20])),
"used" => intval(preg_replace('/[^\d]/','',$ret_top[21])),
"buf_cache" => intval(preg_replace('/[^\d]/','',$ret_top[22])),
],
"cpu"=>[
//ユーザーモードCPU使用率+システムモードCPU使用率
"ussy" => floatval($ret_vmstat[0])+floatval($ret_vmstat[1]),
"id" => floatval($ret_vmstat[2]), //アイドル時間の割合
"wa" => floatval($ret_vmstat[3]), //IO待機時間の割合
]
];
$message=[];
if($val["process"]["zombie"]>=$thresh["process"]["zombie"]){
$message[]=sprintf($warning["process"]["zombie"], $val["process"]["zombie"]);
}
if($val["cpu"]["ussy"]>=$thresh["cpu"]["ussy"]){
$message[]=sprintf($warning["cpu"]["ussy"], $val["cpu"]["ussy"]);
}
if($val["cpu"]["wa"]>=$thresh["cpu"]["wa"]){
$message[]=sprintf($warning["cpu"]["wa"], $val["cpu"]["wa"]);
}
if(count($message)>0){
$head = "From: ".$from."\r\n".
"Reply-To: ".$from;
$body = implode("\r\n", $message);
$body.= "\r\n".
"プロセス数(動作中)" .$val["process"]["running"]."\r\n".
"プロセス数(一時停止)".$val["process"]["sleeping"]."\r\n".
"プロセス数(停止中)" .$val["process"]["stopped"]."\r\n".
"プロセス数(ゾンビ)" .$val["process"]["zombie"]."\r\n".
"\r\n".
"メモリ(未使用)" . $val["memory"]["free"] ."KB\r\n".
"メモリ(使用)" . $val["memory"]["used"] ."KB\r\n".
"メモリ(バッファ/キャッシュ)" . $val["memory"]["buf_cache"] ."KB\r\n".
"\r\n".
"CPU(使用率)" . $val["cpu"]["ussy"] ."KB\r\n".
"CPU(アイドル率)" . $val["cpu"]["id"] ."KB\r\n".
"CPU(IO待ち)" . $val["cpu"]["wa"] ."KB\r\n";
mb_language('uni');
mb_send_mail($to, $subject, $body, $head);
}
