ログ・アーカイブとデータ・マイニング


ログ・アーカイブとデータ・マイニング
http://netkiller.github.io/journal/log.html
Mr.Neo Chen(陳景峰)、netkiller、BG 7 NYT
中国広東省深セン市龍華新区民治街道渓山美地518131+86 1313668890+86 755 29812080
著作権© 2013, 2014 Netkiller. All rights reserved.
著作権声明
転載は作者に連絡してください.転載する時、必ず文章の元の出所と作者の情報と本声明を明記してください.
日志归档与数据挖掘
文書の出典:
http://netkiller.github.io
http://netkiller.sourceforge.net
2014-12-16
サマリ
2013-03-19第1版
2014-12-16第2版
マイシリーズドキュメント
Netkiller Architect手札
Netkiller Developer手札
Netkiller PHP手札
Netkiller Python手札
Netkiller Testing手札
Netkiller Cryptography手札
Netkiller Linux手札
Netkiller Debian手札
Netkiller CentOS手札
Netkiller FreeBSD手札
Netkiller Shell手札
Netkiller Security手札
Netkiller Web手札
Netkiller Monitoring手札
Netkiller Storage手札
Netkiller Mail手札
Netkiller Docbook手札
Netkiller Version手札
Netkiller Database手札
Netkiller PostgreSQL手札
Netkiller MySQL手札
Netkiller NoSQL手札
Netkiller LDAP手札
Netkiller Network手札
Netkiller Cisco IOS手札
Netkiller H 3 C手札
Netkiller Multimedia手札
Netkiller Perl手札
Netkiller Amateur Radio手札
Netkiller DevOps手札
目次
  • 1. ログアーカイブ
  • 2. なぜログアーカイブをするのか
  • 3. ログのアーカイブはいつ行いますか
  • 4. アーカイブ・ログの場所
  • 5. 誰がログのアーカイブをします
  • 6. ログのアーカイブ方法
  • 6.1. ログフォーマット変換
  • 6.1.1.データベースにログを入れる
  • 6.1.2. Apache Pipe
  • 6.1.3. Log format
  • 6.1.4.ログをMongoDB
  • にインポート
  • 6.2. ログ・センター・スキーマ
  • 6.2.1.ソフトウェアインストール
  • 6.2.2.ノードプッシュ端子
  • 6.2.3.ログ収集側
  • 6.2.4.ログモニタ


  • 1.ログのアーカイブ
    アーカイブとは、ログを整理し、保存価値のあるファイルをシステム整理してログサーバに保存するプロセスです.
    2.なぜログのアーカイブを行うのか
  • 履歴ログ照会を随時呼び出します.
  • ログによるデータマイニングを行い、価値のあるデータをマイニングする.
  • アプリケーションの動作状態の表示
  • 3.ログのアーカイブを行うタイミング
    ログアーカイブは企業が規定した制度(「アーカイブ制度」)であり、システム建設当初からログアーカイブの問題を考慮しなければならない.もしあなたの企業にこの仕事や制度がなければ、本稿を読んだ後、すぐに実施することをお勧めします.
    4.アーカイブ・ログの場所
    単一ノードサーバとバックアップスキームを簡単に使用できます.
    ログの規模が拡大するにつれて、将来的には分散ファイルシステムを採用し、遠隔地の災害対応にも関与する必要があります.
    5.誰がログのアーカイブをしますか
    私の答えはログアーカイブの自動化、手動検査、または抜き取り検査です.
    6.ログのアーカイブ方法
    すべてのサーバのログを1つにまとめるには、いくつかの方法があります.
    ログ・アーカイブの一般的な方法:
  • ftpは必ずダウンロードして、このようなやり方は小さいファイルに適してしかもログの量は大きくなくて、必ず指定のサーバーにダウンロードして、欠点は重複して伝送して、リアルタイム性が悪いです.
  • rsyslog類のプログラムは、比較的汎用的であるが、拡張が不便である.
  • rsyncは同期であり、FTPよりもファイル同期に適しており、リアルタイム性が悪い.

  • 6.1.ログフォーマット変換
    まず簡単な案を紹介します
    私はD言語で1つのプログラムを書いてWEBログを正則的に分解してそれからパイプを通じてデータベースのハンドラに伝達します
    6.1.1.データベースにログを入れる
    WEBサーバログをパイプ処理してデータベースに書き込む
    ハンドラソース
    $ vim match.d
    import std.regex;
    import std.stdio;
    import std.string;
    import std.array;
    
    void main()
    {
        // nginx
    	//auto r = regex(`^(\S+) (\S+) (\S+) \[(.+)\] "([^"]+)" ([0-9]{3}) ([0-9]+) "([^"]+)" "([^"]+)" "([^"]+)"`);
    
    	// apache2
    	auto r = regex(`^(\S+) (\S+) (\S+) \[(.+)\] "([^"]+)" ([0-9]{3}) ([0-9]+) "([^"]+)" "([^"]+)"`);
    
    	foreach(line; stdin.byLine)
    	{
    
    		foreach(m; match(line, r)){
    			//writeln(m.hit);
    			auto c = m.captures;
    			c.popFront();
    			//writeln(c);
    			auto value = join(c, "\",\"");
    			auto sql = format("insert into log(remote_addr,unknow,remote_user,time_local,request,status,body_bytes_sent,http_referer,http_user_agent,http_x_forwarded_for) value(\"%s\");", value );
    			writeln(sql);
    		}
    	}
    }

    コンパイル
    $ dmd match.d
    $ strip match
    
    $ ls
    match  match.d  match.o

    簡単な使い方
    $ cat access.log | ./match

    高度な使い方
    $ cat access.log | match | mysql -hlocalhost -ulog -p123456 logging

    ログをリアルタイムで処理し、まずパイプを作成し、そのログファイルを探してパイプに書き込む.
    cat      | match | mysql -hlocalhost -ulog -p123456 logging

    これにより、リアルタイムログ挿入が可能になります.
    ヒント
    上のプログラムは少し修正してHbase,Hypertableの本版を実現することができます
    6.1.2. Apache Pipe
    Apacheログパイプ濾過CustomLog"|/srv/match>/tmp/access.log"combined
    <VirtualHost *:80>
            ServerAdmin webmaster@localhost
    
            #DocumentRoot /var/www
            DocumentRoot /www
            <Directory />
                    Options FollowSymLinks
                    AllowOverride None
            </Directory>
            #<Directory /var/www/>
            <Directory /www/>
                    Options Indexes FollowSymLinks MultiViews
                    AllowOverride None
                    Order allow,deny
                    allow from all
            </Directory>
    
            ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
            <Directory "/usr/lib/cgi-bin">
                    AllowOverride None
                    Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
                    Order allow,deny
                    Allow from all
            </Directory>
    
            ErrorLog ${APACHE_LOG_DIR}/error.log
    
            # Possible values include: debug, info, notice, warn, error, crit,
            # alert, emerg.
            LogLevel warn
    
            #CustomLog ${APACHE_LOG_DIR}/access.log combined
            CustomLog "| /srv/match >> /tmp/access.log" combined
    
        Alias /doc/ "/usr/share/doc/"
        <Directory "/usr/share/doc/">
            Options Indexes MultiViews FollowSymLinks
            AllowOverride None
            Order deny,allow
            Deny from all
            Allow from 127.0.0.0/255.0.0.0 ::1/128
        </Directory>
    
    </VirtualHost>

    パイプを介して変換されたログ効果
    $ tail /tmp/access.log
    insert into log(remote_addr,unknow,remote_user,time_local,request,status,body_bytes_sent,http_referer,http_user_agent,http_x_forwarded_for) value("192.168.6.30","-","-","21/Mar/2013:16:11:00 +0800","GET / HTTP/1.1","304","208","-","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22");
    insert into log(remote_addr,unknow,remote_user,time_local,request,status,body_bytes_sent,http_referer,http_user_agent,http_x_forwarded_for) value("192.168.6.30","-","-","21/Mar/2013:16:11:00 +0800","GET /favicon.ico HTTP/1.1","404","501","-","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22");
    insert into log(remote_addr,unknow,remote_user,time_local,request,status,body_bytes_sent,http_referer,http_user_agent,http_x_forwarded_for) value("192.168.6.30","-","-","21/Mar/2013:16:11:00 +0800","GET / HTTP/1.1","304","208","-","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22");

    6.1.3. Log format
    LogFormatを定義することでSQL形式のログを直接出力できます
    Apache
    LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
    LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
    LogFormat "%h %l %u %t \"%r\" %>s %O" common
    LogFormat "%{Referer}i -> %U" referer
    LogFormat "%{User-agent}i" agent

    Nginx
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';

    しかし、システム管理者がgrep,awk,sed,sort,uniq分析を使用する場合、一定のトラブルが発生します.だから私は依然として正則分解を採用することを提案します
    ルール・ログ・フォーマット、Apache:
    LogFormat \
            "\"%h\",%{%Y%m%d%H%M%S}t,%>s,\"%b\",\"%{Content-Type}o\",  \
            \"%U\",\"%{Referer}i\",\"%{User-Agent}i\""

    アクセスをlogファイルmysqlにインポート
    LOAD DATA INFILE '/local/access_log' INTO TABLE tbl_name
    FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' ESCAPED BY '\\'

    6.1.4.ログをMongoDBにインポート
    # rpm -Uvh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
    # yum install mongodb

    D言語ログハンドラ
    import std.regex;
    //import std.range;
    import std.stdio;
    import std.string;
    import std.array;
    
    void main()
    {
    	// nginx
    	auto r = regex(`^(\S+) (\S+) (\S+) \[(.+)\] "([^"]+)" ([0-9]{3}) ([0-9]+) "([^"]+)" "([^"]+)" "([^"]+)"`);
    	// apache2
    	//auto r = regex(`^(\S+) (\S+) (\S+) \[(.+)\] "([^"]+)" ([0-9]{3}) ([0-9]+) "([^"]+)" "([^"]+)"`);
    	foreach(line; stdin.byLine)
    	{
    		//writeln(line);
    		//auto m = match(line, r);
    		foreach(m; match(line, r)){
    			//writeln(m.hit);
    			auto c = m.captures;
    			c.popFront();
    			//writeln(c);
    			/*
    			SQL
    			auto value = join(c, "\",\"");
    			auto sql = format("insert into log(remote_addr,unknow,remote_user,time_local,request,status,body_bytes_sent,http_referer,http_user_agent,http_x_forwarded_for) value(\"%s\");", value );
    			writeln(sql);
    			*/
    			// MongoDB
    			string bson = format("db.logging.access.save({
    						'remote_addr': '%s',
    						'remote_user': '%s',
    						'time_local': '%s',
    						'request': '%s',
    						'status': '%s',
    						'body_bytes_sent':'%s',
    						'http_referer': '%s',
    						'http_user_agent': '%s',
    						'http_x_forwarded_for': '%s'
    						})",
    						c[0],c[2],c[3],c[4],c[5],c[6],c[7],c[8],c[9]
    						);
    			writeln(bson);
    
    		}
    	}
    
    }

    コンパイルログハンドラ
    dmd mlog.d

    使用法
    cat /var/log/nginx/access.log | mlog | mongo 192.169.0.5/logging -uxxx -pxxx

    エラー・ログの処理
    # zcat /var/log/nginx/*.access.log-*.gz | /srv/mlog | mongo 192.168.6.1/logging -uneo -pchen

    リアルタイム収集ログ
    tail -f /var/log/nginx/access.log | mlog | mongo 192.169.0.5/logging -uxxx -pxxx

    6.2.ログ・センター・スキーマ
    上記のシナリオは簡単ですが、システム管理者に依存しすぎて、多くのサーバを構成する必要があります.アプリケーションごとに発生するログが異なるので、複雑です.途中で障害が発生すると、ログが失われます.
    そこで私はまた起点に戻って、すべてのログは自分のサーバーの上で保存して、定時に彼らをログサーバーに同期して、このようにログのアーカイブを解決しました.リモートでログを収集し、UDPプロトコルを介してログセンターにプッシュしてまとめることで、ログのリアルタイム監視、キャプチャなどのリアルタイム性に対する要求が高いことを解決します.
    そのため、私は2、3日かけてソフトウェアを書いて、住所をダウンロードしました.https://github.com/netkiller/logging
    この案は最適ではありませんが、私のシーンに適しています.そして、私は2、3日でソフトウェアの開発を完了しました.後でさらに拡張して、メッセージキューのログ転送機能を追加します.
    6.2.1.ソフトウェアのインストール
    $ git clone https://github.com/netkiller/logging.git
    $ cd logging
    $ python3 setup.py sdist
    $ python3 setup.py install

    6.2.2.ノードプッシュ端子
    起動スクリプトのインストール
    CentOS
    # cp logging/init.d/ulog /etc/init.d

    Ubuntu
    $ sudo cp init.d/ulog /etc/init.d/	
    
    $ service ulog 
    Usage: /etc/init.d/ulog {start|stop|status|restart}

    スクリプトを構成し、/etc/initを開きます.d/ulogファイル
    ログセンターのIPアドレスの設定
    HOST=xxx.xxx.xxx.xxx

    ポートを構成し、ログを取得します.
    done << EOF
    1213 /var/log/nginx/access.log
    1214 /tmp/test.log
    1215 /tmp/$(date +"%Y-%m-%d.%H:%M:%S").log
    EOF

    書式
    Port | Logfile
    ------------------------------
    1213 /var/log/nginx/access.log
    1214 /tmp/test.log
    1215 /tmp/$(date +"%Y-%m-%d.%H:%M:%S").log

    1213宛先ポート番号(ログセンターポート)の後ろには、ログが毎日/tmp/$(date+"%Y-%m-%d.%H:%M:%S")のようなファイルを生成する場合に監視する必要があるログがあります.log
    毎日1つの新しいログファイルを生成するためにulogをタイミング的に再起動する必要があることを示す方法は/etc/initである.d/ulog restart
    構成完了後にプッシュプログラムを起動する
    # service ulog start

    ステータスの表示
    $ service ulog status
    13865 pts/16   S      0:00 /usr/bin/python3 /usr/local/bin/rlog -d -H 127.0.0.1 -p 1213 /var/log/nginx/access.log

    プッシュストップ
    # service ulog stop

    6.2.3.ログ収集側
    # cp logging/init.d/ucollection /etc/init.d
    
    # /etc/init.d/ucollection 
    Usage: /etc/init.d/ucollection {start|stop|status|restart}

    受信ポートと保存ファイルを構成し、/etc/initを開く.d/ucollectionファイル、次の段落が表示されます
    done << EOF
    1213 /tmp/nginx/access.log
    1214 /tmp/test/test.log
    1215 /tmp/app/$(date +"%Y-%m-%d.%H:%M:%S").log
    1216 /tmp/db/$(date +"%Y-%m-%d")/mysql.log
    1217 /tmp/cache/$(date +"%Y")/$(date +"%m")/$(date +"%d")/cache.log
    EOF

    フォーマットは、1213ポートからのデータを受信、/tmp/nginx/accessに保存することを示す.logファイルにあります.
    Port | Logfile
    1213 /tmp/nginx/access.log

    ログを分割する必要がある場合は、次のように構成します.
    1217 /tmp/cache/$(date +"%Y")/$(date +"%m")/$(date +"%d")/cache.log

    上の構成ログファイルは、次のディレクトリに生成されます.
    $ find /tmp/cache/
    /tmp/cache/
    /tmp/cache/2014
    /tmp/cache/2014/12
    /tmp/cache/2014/12/16
    /tmp/cache/2014/12/16/cache.log

    ヒント同様に、ログを分割するには収集側プログラムを再起動する必要があります.
    収集の開始
    # service ulog start

    ていしルーチン
    # service ulog stop

    ステータスの表示
    $ init.d/ucollection status
    12429 pts/16   S      0:00 /usr/bin/python3 /usr/local/bin/collection -d -p 1213 -l /tmp/nginx/access.log
    12432 pts/16   S      0:00 /usr/bin/python3 /usr/local/bin/collection -d -p 1214 -l /tmp/test/test.log
    12435 pts/16   S      0:00 /usr/bin/python3 /usr/local/bin/collection -d -p 1215 -l /tmp/app/2014-12-16.09:55:15.log
    12438 pts/16   S      0:00 /usr/bin/python3 /usr/local/bin/collection -d -p 1216 -l /tmp/db/2014-12-16/mysql.log
    12441 pts/16   S      0:00 /usr/bin/python3 /usr/local/bin/collection -d -p 1217 -l /tmp/cache/2014/12/16/cache.log

    6.2.4.ログ監視
    1217ワイドポートからのデータの監視
    $ collection -p 1213
    
    192.168.6.20 - - [16/Dec/2014:15:06:23 +0800] "GET /journal/log.html HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
    192.168.6.20 - - [16/Dec/2014:15:06:23 +0800] "GET /journal/docbook.css HTTP/1.1" 304 0 "http://192.168.6.2/journal/log.html" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
    192.168.6.20 - - [16/Dec/2014:15:06:23 +0800] "GET /journal/journal.css HTTP/1.1" 304 0 "http://192.168.6.2/journal/log.html" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
    192.168.6.20 - - [16/Dec/2014:15:06:23 +0800] "GET /images/by-nc-sa.png HTTP/1.1" 304 0 "http://192.168.6.2/journal/log.html" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
    192.168.6.20 - - [16/Dec/2014:15:06:23 +0800] "GET /js/q.js HTTP/1.1" 304 0 "http://192.168.6.2/journal/log.html" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"

    起動後に最新ログをリアルタイムで送信