マシンの接続をpingで監視し、必要ならWOLで起こすスクリプト「okiro.php」

 pingWOLの合わせ技です。私の場合はindex.phpに改名して玄箱の880ポートのドキュメントルートに置きました。digest認証に守られているので一応安全かと。LAN内からはIPアドレス直打ちで、外からはダイナミックDNSでアクセスしてます。ルータの設定をいじることなく、ルータ越えのWOLを実現できたわけです。自分が使うには満足なものができました。
 pingによる監視はLAN内で固定IPが振られている(DHCPを使ってない)場合、意味があります。また、www.yahoo.comのように与えても当然機能しますので、サイトの生存確認にも利用できます。WOL機能はMACアドレスだけ与えれば機能するのでhttp://...../okiro.php?m=66778899AABBをブックマークしておくとWOL単機能トリガーになります。
 使う分には自己責任でおねがいします。コメントでも残しておいてもらえると嬉しいかも。

<?php
/**
 * okiro.php
 * マシンの接続をpingで監視し、必要ならWOLで起こします
 * by iphlox
 * ver 081115
 * 要PEAR::Net_Ping
 * エラー処理とかは適当
 * GETパラメータmにmacアドレス入れれば動くのは仕様です
 * mに変な値を入れてネットワークが壊れても知りません
 * WOL送出後はリファラーへリダイレクトするのも仕様です
 */

/*
 * 設定
 * 
 * $watchlist
 * 監視対象の情報
 * nameは表示に使うだけで空白可
 * host必須 IPアドレスまたは完全なホスト名(例www.yahoo.co.jp)
 * WakeOnLANする場合はMACアドレスを12文字連続で
 * 
 * $refresh
 * リロード間隔(秒)
 * 
 * $broadcast
 * ブロードキャストアドレス
 * 
 * $th,$st,$okiroは画面表示用の文字列なのでお好みで
 * 
 */
$watchlist = array(
    array('name' => 'kuro',     'host' => '192.168.1.19', 'mac' => ''),
    array('name' => 'mac',      'host' => '192.168.1.11', 'mac' => '001122334455'),
    array('name' => 'windows',  'host' => '192.168.1.13', 'mac' => '66778899AABB')
);
$refresh = 60;

$broadcast = '192.168.1.255';

//WOL送出後はリファラーへリダイレクト
//LANとWANでIPは違うのでこんな方法しか思いつかん
$redirect = $_SERVER["HTTP_REFERER"];

$th = array(
    'name'      => '名前',
    'host'      => 'アドレス',
    'status'    => 'ステータス',
    'control'   => 'アクション'
);

$st = array(
    'off'   => 'Zz.(-_-)',
    'on'    => '(^o^)',
);

$okiro = '○=(`Д´)';


/*
 * メイン
 */
require_once "Net/Ping.php";

if($_GET['m']){

    //WOL処理
    $body = h2s('FFFFFFFFFFFF');
    for($i=0;$i<20;$i++) {
        $body .= h2s($_GET['m']);
    }
    $soc = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
    socket_set_option($soc, SOL_SOCKET, SO_BROADCAST, 1);
    socket_connect($soc, $broadcast, 2304);
    socket_write($soc, $body, 126);
    socket_close($soc);
    
    header("Location: {$redirect}");
    
}else{
    //ステータス表示
    $ping = Net_Ping::factory();
    $content = "";
    
    if (PEAR::isError($ping)) {
        echo $ping->getMessage();
    } else {
        $ping->setArgs(array('count' => 1));
        
        $content .= "<table>\n<tr>\n";
        $content .= "<td>{$th['name']}</td>";
        $content .= "<td>{$th['host']}</td>";
        $content .= "<td>{$th['status']}</td>";
        $content .= "<td>{$th['control']}</td>";
        $content .= "</tr>\n";
        foreach($watchlist as $watch){
            $status = ! $ping->ping($watch['host'])->_loss;
            $status_view = $status ? $st['on'] : $st['off'];
            $control_view = $status ? '' 
                : "<a href='?m={$watch['mac']}'>{$okiro}</a>\n";
            
            $content .= "<tr>\n";
            $content .= "<td>{$watch['name']}</td>\n";
            $content .= "<td>{$watch['host']}</td>\n";
            $content .= "<td>$status_view</td>\n";
            $content .= "<td>$control_view</td>\n";
            $content .= "</tr>\n";
        }
        $content .= "</tr>\n</table>\n";
    }
}


function h2s($h) {
    $s = '';
    $p = 0;
    while($p<strlen($h)) {
        $s .= chr(intval(substr($h, $p, 2), 16));
        $p += 2;
    }
    return $s;
}


?>
<html>
<head>
<meta http-equiv="Refresh" content="<?php echo $refresh; ?>">
<title>okiro</title>
<style>
*{
  padding: 0px;
  margin: 0px;
  font-family: Helvetica;
}
a{
    text-decoration : none ;
}
table{
    border-collapse:collapse;
}
td{
    padding-top : 20px ;
    font-size : 300% ;
    text-align : center;
    border-bottom : solid 1px #888888 ;
}
</style>
</head>
<body>
<?php echo $content; ?>
</body>
</html>