何の話?
サーバ冷却用の扇風機を、サーバのHDDやCPUの温度に連動させて自動的に動かしたり止めたりしましょうというお話。
使うもの
・Hardware
リレー制御ボード RBIO-3E
少し大きめのリレーでAC100VをON/OFFする回路
・Software
hddtemp
LinuxでハードディスクのS.M.A.R.T.情報から温度を取得するツール。
デーモンとして起動して、ソケット通信で結果を取得できるので使いやすい。
mbmon
Linuxでマザーボードが報告する温度やらファン回転数やらを取得するソフト。
hddtemp同様、ソケット通信で結果を取得できる。
同梱されてるxmbmonはX上でグラフを表示してくれるが、
今回はサーバ用途なのでmbmonしか使わない。
hddtempとmbmonの使い方
・インストール
どちらもソースを落としてきて./configureしてmakeして出来たバイナリを、パスの通った場所に置くだけで完了の簡単インストール。
hddtempは
で、このhddtemp.dbってのに自分の使ってるHDDが入ってなかったら動かないので、上記リンク先にある最新hddtemp.dbを落としておくか、自分の使うHDDだけ抜粋して書いておく。自分の使ってるHDDが無い場合、同じメーカーの近い型番のものを参考に、それっぽく書き換えると一応使える。
・起動
hddtempは
/dev/hda: Maxtor 6L160P0: 42°C
/dev/hdb: WDC WD2500JB-00REA0: 40°C
/dev/hdc: MAXTOR 6L080L4: 50°C
/dev/hdd: Maxtor 6L080P0: 41°C
ただし、/dev/hdaとかにアクセス権がないとダメなので、rootでやるかsudoでやるかしないとダメ。
mbmonは
Temp.= 127.0, 20.0, 127.0; Rot.= 0, 0, 0
Vcore = 1.44, 1.49; Volt. = 3.26, 4.97, 11.31, -5.56, -2.19
Temp.= 127.0, 19.0, 127.0; Rot.= 0, 0, 0
Vcore = 1.44, 1.49; Volt. = 3.26, 4.97, 11.37, -7.84, -4.55
今回欲しいのは温度なわけだが、どれが何の温度かはマザーボードに依存するので分からない。
そして今俺のサーバマシンに使ってるASRocのP4i65Gでは、おそらくCPU温度と思われる2番目の温度が室温以下とかいうあり得ない数字を叩き出す。
まぁ、負荷をかけたら上がるので、絶対的に正確でなくても、基準を設けてそれより高いか低いかの区別は付くので大きな問題ではない。
これもhddtemp同様デーモンとして起動するわけだが、
・データの取得
PHPで
//hddtemp
$host = localhost;
$port = ****; //hddtempのポート番号
$socket = fsockopen($host,$port);
$hddtemp_result = fgets($socket,1024);
fclose($socket);
//mbmon
$port = ****; //mbmonのポート番号
$socket = fsockopen($host,$port);
fgets($socket,1024);
$mbmon_result = fgets($socket,1024);
fclose($socket);
echo <<<EOH
<html>
<head>
</head>
<body>
<pre>{$hddtemp_result}</pre>
<br />
<pre>{$mbmon_result}</pre>
</body>
</html>
EOH;
?>
Temp.= 127.0, 19.0, 127.0; Rot.= 0, 0, 0
まぁ、見た感じhddtempは、
mbmonは一見じゃまくさそうな形してるけど、幸い俺が欲しいのは2つめの温度なので、『,』でsplitして2つめを取得するだけでいい。
本題
以上の内容を踏まえて、本題である『扇風機を自動でON/OFFする』を実現するPHPスクリプトを書く。
・仕様
1.一定時間ごとに温度を確認してスイッチを切り替える
2.各デバイスごとに温度の閾値を個別設定する
3.常時ONや常時OFFの設定も可能にする
・ソース
/*************************************************************************************************
Name : fan_control.php
Acthion : 温度条件でRBIO-3Eの0番リレーを制御して扇風機をON/OFFする。
バックグラウンドで動作させる。
2008.06.22 Ver.0.01 Genki wrote
2008.07.14 Ver.0.02 Genki edit.
仕様
./modeファイルから動作モードを取得する(on,off,auto)
mbmonとhddtempからの情報で切り替える
while(1)でループ処理。
(起動コマンドの最後に&をつけてバックグラウンドで実行する。)
***************************************************************************************************/
while(1){
//各種温度取得
//vine hddtemp
$host = "localhost";
$port = ****; //hddtempのポート番号
$sock = fsockopen($host,$port);
$result = trim(fgets($sock,1024));;
$result = strtr($result, '|', ',');
$trim = list(,,,$hdd[0],,,,,$hdd[1],,,,,$hdd[2],,,,,$hdd[3],) = split (",", $result);
fclose($sock);
//vine mbmon
$port = ****; //mbmonのポート番号
$sock = fsockopen($host,$port);
fgets($sock,1024);
$result = trim(fgets($sock,1024));
list(,$cpu[0],) = split(",",$result,3);
$cpu[0] = str_replace(' ','',$cpu[0]);
fclose($sock);
//Firewall hddtemp
$host = "firewall";
$port = ****; //ルータ機のhddtempのポート番号
$sock = fsockopen($host,$port);
$result = trim(fgets($sock,1024));;
$result = strtr($result, '|', ',');
$trim = list(,,,$hdd[4]) = split (",", $result);
fclose($sock);
//Firewall mbmon
$port = ****; //ルータ機のmbmonのポート番号
$sock = fsockopen($host,$port);
fgets($sock,1024);
$result = trim(fgets($sock,1024));
list(,$cpu[1],) = split(",",$result,3);
$cpu[1] = str_replace(' ','',$cpu[1]);
fclose($sock);
//条件設定
if($hdd[0] > 45 || $hdd[1] > 42 || $hdd[2] > 52 || $hdd[3] > 45 || $hdd[4] > 35 || $cpu[0] > 27 || $cpu[1] > 38){
$fan = "on";
}else{
$fan = "off";
}
//RBIO接続
$host = "rbio";
$port = ****; //rbioの待ち受けポート
while(1){
$sock = fsockopen($host,$port,$errorno,$errormsg,3);
if(!$sock){
sleep(1);
continue;
}else{
break;
}
}
//現在のスイッチ状態を把握
fputs($sock,"PCA0\n");
fgets($sock,16);
$status = fgets($sock,16);
fgets($sock,16);
//動作モードget
$mode = file("/etc/rbio/fan_mode");
$mode = str_replace("\n",null,$mode[0]);
//スイッチ状態を変化させる必要がある場合に切り替える。
//################################################
//#####注意! 0番リレーがONのとき扇風機がOFF #####
//################################################
//現状ONの場合、OFFにする作業だけする。
if(ereg("0",$status)){ //RBIOのリレーがオフということは現在扇風機ON
if($mode == "off" || $mode == "auto" && $fan == "off"){
fputs($sock,"PCR01\n");
fgets($sock,16);
$res = fgets($sock,16);
}
//現状OFFの場合、ONにする作業だけする。
}else{
if($mode == "on" || $mode == "auto" && $fan == "on"){
fputs($sock,"PCR00\n");
fgets($sock,16);
$res[$i] = fgets($sock,16);
}
}
fclose($sock); //他で使うためにコネクションクローズ
sleep(300); //5分ごとのチェックでいいかな。
}
?>
/etc/rbio/fan_modeというファイルを作っておいて、中身をauto,on,offの3種類のどれかに外部から書き換えることで、動作モードを変更できる。
rbioは同時に1つしか接続を受け付けてくれないので、使う直前にfsockopenし、使ったらすぐfcloseする。
while(1)で無限ループするので、起動時に
この起動コマンドを/etc/rc.d/rc.localの下の方にフルパスで付け足して、サーバ再起動時にも動くようにしておく。
とおりすがり
自宅サーバなんだからcronじゃ駄目なの?
げんき
ん~たぶんwhileループをナシにしてcronで実行しても一緒かなぁ。
起動しっぱなしにしてるとずっとメモリを占有するから、cronで起動して、終わったらメモリ解放のほうがいいのかな?
分かりません。
まぁ、今回はデーモンっぽくバックグラウンドで動かし続けてみたかっただけです。