kazpgmの日記

『プログラム自動作成@自動生成』作成の日記

いろいろなLogをWEB画面にtailするphp+Ajaxを発見した。

いろいろなLogをWEB画面にtailするphpAjaxを発見した。
・仕事用にpostgresのlogを常時解析するプログラムを作りたいと思って、会社の人にphpでpostgresのログを常時取得する方法はないかなと聞いたら、tailみたいにしたらどう。っていわれたので、今日phpとtailでGoogleた。
・そしたら面白いプログラムを見つけた。調べたかったものとは少し違うけど、あまりにも簡単にすごく興味のある結果が得られるので日記することにした。

・「TAIL」ボタンを押すとtail実行、「STOP」ボタンを押すと更新が止まります。PGM改変後の私のローカルマシンでの画面です。
   ログの場所は「phptail.php」のdefine定義に書いてあります。画面はAjaxで2000ミリ秒に1回書き換えています。php中のログファイルを変えていろいろ表示するのは面白そう。

改変後のphpです。(注意:UTF-8で保存すること。)ソースにコメントを付加しました。出力できるログを増やしました。元ねたURLは以下ソース中に書いておきました。

<?php
// ■phptail.php
// 2010/01/23 kazpgm:提供元(以下URL参照)から抜粋してコメントを付加したものです。
// あと、ファイルを指定できるようにしてみました。(ファイル名はセキュリティ保持のため、画面入力しません。)
// http://techblog.ecstudio.jp/tech-tips/phptail.html (jQueryとPHPでLinuxのtailコマンドを実装する)
// 
// −−<<提供元WEBページから抜粋 start>>
//  とても短いソースコードなので、業務の用途にあわせて
//  改変していただければなと思います。
// 
//  今回はとてもシンプルにただ1つのファイルを監視するだけですが、
//  PHPを改造すればローテートされる複数のログファイルを横断したり、
//  正規表現で抜き出したり、自由自在にファイルを
//  監視するスクリプトを作れるのではないかと思います。
// 
//  ただ注意しなければいけないのが、監視対象のファイルを
//  GET値などで指定できるようにすると、セキュリティ上
//  非常に危ないのでそういった改造をする場合は
//  注意するようにしてください。
// 
//  このソースコードは自由に使用していただいて構いませんが、
//  各自の自己責任での使用をお願いします!  
// −−<<提供元WEBページから抜粋 end>>

    header('Content-type:text/html; charset=UTF-8');
    
    // 2010/01/23 kazpgm start:ここにlog_idを追加しました。
    // アパッチアクセスログ
    define('DIR_ACCESS_LOG', 'C:\xampp\apache\logs\access.log');
    // アパッチエラーログ
    define('DIR_ERROR_LOG', 'C:\xampp\apache\logs\error.log');
    //対象のファイルパス
    $logpath = DIR_ACCESS_LOG;
    //$logpath = 'C:\xampp\apache\logs\access.log';
    if (isset($_GET['log_id'])){ // GETで'log_id'パラメータがある場合
        if ($_GET['log_id']=='1') {
            $logpath = DIR_ACCESS_LOG; // アパッチアクセスログ
        } else if ($_GET['log_id']=='2') {
            $logpath = DIR_ERROR_LOG; // アパッチエラーログ
        }
    }
    // 2010/01/23 kazpgm end:ここにlog_idを追加しました。

    //表示する末尾の行数
    $lines = 30;
    //更新インターバル (ミリ秒)
    $interval = 2000;
    
    if (isset($_GET['load'])){ // GETで'load'パラメータがある場合
        echo 'file:'.basename($logpath).' reload:'.date('H:i:s').'<hr size="1"/>'; // 例)file:access.log reload:17:39:39
        
        if (!file_exists($logpath)){ // 対象のファイルがない場合
            die($logpath.'は存在しません'); // ファイルがないというメッセージを戻す。
        }
        
        foreach (read_tail($logpath,$lines) as $i => $line){ // ログをファイルから指定行数読み出した行ごとの配列を読み込む。
            $line = rtrim($line,"\r\n"); // 文字列の末尾から"\r\n"を削除する
            // 行中の特殊文字を HTML エンティティに変換する。タブは'&nbsp;&nbsp;&nbsp;&nbsp;'に変換する。
            echo strtr(htmlspecialchars($line,ENT_QUOTES),array("\t" => '&nbsp;&nbsp;&nbsp;&nbsp;'));
            if ($i <($lines - 1)){ // 最終行以外の場合
                echo '<br />'; // HTML改行を出す。
            }
        }
        
        exit;
    }
    
/**
* ログをファイルから指定行数読み出す
* 
* tail function by flash tekkie
* http://tekkie.flashbit.net/php/tail-functionality-in-php
* 
* @param string $file ファイルパス
* @param int $lines 行数
* @return array 行ごとの配列
*/
function read_tail($file, $lines) {
    //global $fsize;
    $handle = fopen($file, "r"); // 読み込み。ポインタは先頭。
    $linecounter = $lines; // 未読み込みカウンタ
    $pos = -2; // シークバイト(初期値はファイル終点から-2バイト(\r\nぶん))
    $beginning = false;     // 
    $text = array(); // 行ごとの配列
    while ($linecounter> 0) { // 読み込み行数までループ
        $t = " "; // 1文字(初期値)
        while ($t != "\n") { // 1文字が"\n"になるまでループ
            if(fseek($handle, $pos, SEEK_END) == -1) { // ファイルの終端からシークバイトぶん移動させる。
                $beginning = true; // ファイル先頭まで来た
                break; 
            }
            $t = fgetc($handle); // 1文字読み込み
            $pos --; // シークバイトを1バイト1つ前にする。
        }
        $linecounter --;// 未読み込みカウンタを-1する。
        if ($beginning) { // ファイル先頭なら
            rewind($handle); // ファイルポインタの位置を先頭に戻す。
        }
        $text[$lines-$linecounter-1] = fgets($handle); // 行ごとの配列に1行ぶん入れる。(新しいものがインデックス0)
        if ($beginning) break; // ファイル先頭なら終わり。
    }
    fclose ($handle); // ファイルを閉じる
    return array_reverse($text); // 行ごとの配列の順番を逆順(古いものがインデックス0)にして戻す。
}
?>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta name="robots" content="noindex,nofollow" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js"></script>
<script type="text/javascript">
var timer = null; // インターバル値
// TAILボタン押下の処理
function start_tail(){
    if (timer){ // インターバルが設定済みの場合
        clearInterval(timer); // インターバルをクリアする。
    }
    $('#status').html('running...'); // id=statusの箇所に'running...'を書く。
    timer = setInterval(run,<?php echo $interval ?>); // setIntervalでrunという関数を定期的に実行しています。
}
 
// TAILボタン押下でインターバルに設定される処理
function run(){
    // id="console"のタグの中身に対して、
    // '?load=1&m=タイムスタンプ' のURLの実行結果を読み込みます。
    // "m=タイムスタンプ"の部分は、IEの場合
    // Ajaxで同じURLを連続して読み出した場合に
    // キャッシュされてしまうため、URLを毎回変化させています。
    // PHP側ではこのmの値は全く使用しません。

    // 2010/01/23 kazpgm start:ここにlog_idを追加しました。
    //$('#console').load('?load=1&m=' + new Date().getTime());
    $('#console').load('?load=1&m=' + new Date().getTime() + '&log_id=' + document.frm.log_id.value);
    // 2010/01/23 kazpgm end:ここにlog_idを追加しました。
}
 
function stop(){
    clearInterval(timer); // インターバルをクリアする。
    $('#status').empty(); // id=statusの箇所をからにする。
}
</script>
<style type="text/css">
#console {
    width:800px;
    height:500px;
    overflow:scroll;
    border:1px solid #999999;
    font-size:12px;
    font-family:consolas;
}
</style>
</head>
<body>
<?php
// 2010/01/23 kazpgm start:ここにlog_idを追加しました。
?>
<form name="frm">
<select name="log_id">
<option value='1' >アパッチアクセスログ</option>
<option value='2' >アパッチエラーログ</option>
</select>
<?php
// 2010/01/23 kazpgm end:ここにlog_idを追加しました。
?>
<input type="button" onclick="start_tail()" value="TAIL"> 
<input type="button" onclick="stop()" value="STOP"> 
<span id="status"></span><br />
<pre id="console"></pre>
</form>
</body>
</html> 

補足:作ろうと思っているのは、これ
1.postgresを使っている既存ACCESSのやWEBの実行時SQLを解析したい。
2.業務画面を実際に動かしてそのSQL結果から手がかりを得よう。と考えた。

  • ACCESSやWEBを実行する。(解析したいプログラムの単位)
  • postgresのlogから指定時間から現在時間までの指定DBを抜き取って、SQLを人間が見れるきれいなフォーマットに編集してエクセルに貼り付ける。取得した時間をエクセルに保存しておく。
  • これを繰り返す。

そのた:なんと今日はじめて、■ 入力したコードやはてな記法をそのまま表示する(スーパーpre記法)を知った。今まで<pre>を使っていた。すごく使いづらかった。なんと”||<”、”>||”で囲むと中身がそのまま表示される。・・・・・ほしかったもの。やっぱりあるはず、、、、思ってたとおり。だった。・・・・・気づくの遅すぎ?かな。

2010/01/23 03:00-19:00 20:30-24:00