古いファイルを消したいときにtmpwatchを使うと簡単に消すことができます。
例えば、/var/www/app/tmp
配下の48時間以上前のファイルやディレクトリを消したい場合は以下で消せます。
1 | tmpwatch -m 48 /var/www/app/tmp |
tmpwatchは再帰的にファイルを削除するので、サブディレクトリがあればその配下のファイルも削除されます。
シンボリックの場合はリンクが削除されるだけでリンク先のファイルは削除されないとのことです。
前回の記事でFluentdを使ってログをログ収集サーバに転送する方法を紹介しました。
今回は転送されたログをElasticsearchに登録し、Kibanaでログ検索とグラフ表示する方法を紹介します。
ログ収集サーバー(前回の記事でいうVagrant)の変更を行っていきます。
まずは、FluetndのElasticsearchプラグインをインストールしておきます。
1 | $ sudo /usr/sbin/td-agent-gem install fluent-plugin-elasticsearch |
Elasticsearchを動かすにはJavaが必要なのでJavaをインストールします。
1 | $ sudo yum install java-1.7.0-openjdk |
今回はアーカイブをダウンロードしてきてインストールします。
インストールといっても特に設定は不要でアーカイブを展開してbin/elasticsearch
を実行するだけです。
1 | $ curl -O https://download.elastic.co/elasticsearch/release/org/elasticsearch/distribution/tar/elasticsearch/2.3.3/elasticsearch-2.3.3.tar.gz |
Kibanaも同じようにアーカイブをダウンロードして起動します。
1 | $ curl -O https://download.elastic.co/kibana/kibana/kibana-4.5.1-linux-x64.tar.gz |
http://192.168.33.10:5601
にブラウザでアクセスするとKibanaの管理画面が表示されます。
Indexの設定が必要ですが、ここでは何もせず次に進みます。
syslogのログをElasticsearchに格納し、Kibanaで参照します。
/etc/td-agent/td-agent.conf
に以下を追記します。
1 | <source> |
fluendをリスタートします。
1 | $ sudo service td-agent restart |
次にsyslogの設定をします。
/etc/rsyslog.conf
に以下を追記します。
syslogが出力するログをFlutedがlistenするポート、42185に転送するための設定です。
1 | *.* @127.0.0.1:42185 |
設定を反映させるため、syslogをリスタートします。
1 | $ sudo /etc/init.d/rsyslog restart |
先ほど確認した http://192.168.33.10:5601
に戻ります。
syslogの出力がElasticsearchに登録されると、Indexを登録できるようになります。
Indexはlogstash-2016.07.05
のような名前で作成されます。
セレクトボックスからIndexを選択し、Createボタンを押下後にKibanaでログの表示、検索が行えます。
手動でElasticsearchにログを送りたい場合は以下のコマンドで登録できます。
1 | logger -t test foobar |
もしくは、Fluentdのhttpポートにリクエストします。
1 | $ curl -X POST -d 'json={"json":"Hello"}' http://localhost:8888/syslog.test |
アプリケーションサーバとログ収集サーバにFluentdをインストールし、アプリケーションサーバからログ収集サーバにログをフォワードする方法を紹介します。
ここでは、アプリケーションサーバをMacOS X、ログ収集サーバをVagrantとします。
.dmgをダウンロードしてインストールしてください。
以下でFluentdを起動します。
1 | $ sudo launchctl load /Library/LaunchDaemons/td-agent.plist |
Fluentdのログは /var/log/td-agent/td-agent.log
に出力されます。
1 | $ less /var/log/td-agent/td-agent.log |
停止は以下です。
1 | $ sudo launchctl unload /Library/LaunchDaemons/td-agent.plist |
設定ファイルは /etc/td-agent/td-agent.conf
です。
設定を反映させるには、以下のコマンドで行います。
1 | $ sudo launchctl stop td-agent |
以下でFluentdにリクエストします。
1 | $ curl -X POST -d 'json={"json":"message"}' http://localhost:8888/debug.test |
/var/log/td-agent/td-agent.log
にログが出力されているはずです。
1 | $ tail -n 1 /var/log/td-agent/td-agent.log |
次にログ収集サーバにFluentdをインストールします。
OSはCentos6.5を使いました。
vagrantの使い方は割愛します。
networkはprivate_networkとし、192.168.33.10でアクセスできることとします。
以下でログ収集サーバにログインします。
1 | $ vagrant ssh |
ログ収集サーバでも同じように確認してみます。
1 | $ curl -X POST -d 'json={"json":"message"}' http://localhost:8888/debug.test |
アプリケーションサーバからログ収集サーバのFluentdにリクエストを送れるかを確認します。
1 | $ curl -X POST -d 'json={"json":"message"}' http://192.168.33.10:8888/debug.test |
ログ収集サーバでログを確認します。
Fluentdは出力をバッファするのでフォワードされるまでにタイムログがある場合があります。
1 | $ tail -n 1 /var/log/td-agent/td-agent.log |
疎通を確認できたら、アプリケーションサーバからログ収集サーバのFluentdにログをforwardしてみましょう。
アプリケーションサーバの/etc/td-agent/td-agent.conf
を以下のように編集します。
1 | <source> |
ログ収集サーバの/etc/td-agent/td-agent.conf
に以下の設定を追加します。
tagがvagrantで送られてきたものをログに出力します。
1 | <match vagrant.**> |
以下のコマンドでログ収集サーバのFluentdにデータがフォワードされます。
1 | $ curl -X POST -d 'json={"json":"Fluentd!!!"}' http://localhost:8888/vagrant.test |
以上で基本的なフォワードの設定ができました。
次はファイルを監視してファイルにデータが追加されたらその内容をログ収集サーバにフォワードするようにします。in_tail
プラグインを使います。in_tail
プラグインを使うにはtypeにtailを使います。
アプリケーションサーバの/etc/td-agent/td-agent.conf
に以下を追記します。
1 | <source> |
設定を反映させるには、以下のコマンドで行います。
1 | $ sudo launchctl stop td-agent |
/tmp/access_log
に追記してみましょう。
1 | $ echo "hello" >> /tmp/access_log |
すると、ログ収集サーバのFluentdに内容がフォワードされます。
参考リンク
ハフマン符号とは1952年にデビッド・ハフマンという人が考え出したアルゴリズムです。
文字列をはじめとするデータの可逆圧縮に使われます。
よく使われる文字には短いビットを、あまり使われない文字には長いビットを割り当てることで全体としてサイズが削減されることを狙ったアルゴリズムです。
実際にアルゴリズムを確認していきます。
DAEBCBACBBBC
という12文字のメッセージをハフマン符号化します。
このメッセージでは、ABCDEという5種類の文字が使われているため、それぞれの文字を固有のビット長で表す場合は、3ビットが必要です。
1 | A: 000 |
上記の対応表をもとに、文字列をビットに変換します。
1 | DAEBCBACBBBC |
1文字3ビットで12文字あることから全体のビット数は36ビットとなります。
ここで、よく出てくる文字には短いビットを、あまりでてこない文字には短いビットを与えます。
対応表を以下のように作ります。
1 | A: 110 |
メッセージ全体では以下のようになります。
1 | DAEBCBACBBBC |
全体のビット数は25ビットとなり、固定長の方式と比べると70%ほどのデータ量に抑えられています。
以下の手順で文字とビット列の対応表をつくります。
ハフマン木の構成の仕方は次のアルゴリズムとなります。
DAEBCBACBBBC
を題材に、ハフマン木を作ります。
まずは、各記号に対応する葉を作成し、データの出現回数をあらかじめ格納しておきます。
1 | {"B"=>5, "C"=>3, "A"=>2, "D"=>1, "E"=>1} |
DとEが1番小さいので、この2つを取り出します。
そして、DとEの葉を足し合わせた節を1つ作ります。
この手順を最終的に葉が1つになるまで繰り返します。
DAEBCBACBBBC
を作成した対応表で符号化します。
文字 | 個数 | 符号
B | 5 | 0
C | 3 | 10
A | 2 | 110
D | 1 | 1110
E | 1 | 1111
一般的にデータ圧縮アルゴリズムは「モデル化」と「符号化」の2つにわけて考えることができます。
「モデル化」は入力された記号(データ)から各記号の出現確率を求めます。
「符号化」は出現確率に基づいて符号語を割り当て、入力されたデータを各符号語に変換して出力します。
モデル化についてはいろいろな方法がありますが、ハフマン符号のように記号の出現確率を求めそれに基づいて符号語を割り当てるモデルを「無記憶情報源モデル」といいます。
「情報源」は記号を生成する基となるデータのことです。
情報源が記号を生成するとき、以前に生成した記号との間に関連性がないことを「無記憶」といいます。
記号aの次は記号bが生成されるといった関係性はなく、確率でのみ記号が作成されるということです。
データ圧縮アルゴリズムを評価する場合、圧縮率のほかに「平均符号長」という尺度があります。
これは、符号化された記号列のビット長を入力された記号数で割った値として定義されます。
たとえば DAEBCBACBBBC
をハフマン符号化すると1110110111101001101000010
となります。
符号化された記号列のビット長(1110110111101001101000010)を入力された記号数(DAEBCBACBBBC)で割ると平均符号長は 25 / 12 = 2.0833333 となります。
無記憶情報源モデルの場合、各記号 $$ a_i $$ の出現確率 $$ p(a_i) $$ がわかると、次の式で平均符号長の下限値を求めることができます。
$$ H=-\sum_{i=1}^n p(a_i) \log _2 p(a_i) $$
$$ H $$ を平均情報量、またはエントロピー(Entropy)と呼びます。
情報源符号化定理によると、平均符号長はエントロピーより短くすることができません。
意復号可能な平均符号長 L は、無記憶情報源のエントロピー H よりも小さくすることができない。すなわち不等式 H <= L が成り立つ。また、平均符号長 L が H <= L < H + 1 を満足する瞬時に復号可能な符号が構成できる。
先ほどの記号列のエントロピーを求めてみます。
1 | 記号列: DAEBCBACBBBC |
したがって、この記号列では平均符号長を 2.05 ビット以下にすることはできません。
いいかえると、この記号列を表すには少なくても 12 * 2.054585169337799 = 24.65502203205359 ビット以上が必要になる、ということです。
エントロピーを算出するコードをRubyで書きました。
以下のように使います。
1 | $ ./entropy file.txt |
文字列を渡す場合はパイプで繋ぎます。
1 | $ echo "DAEBCBACBBBC" | ./entropy |
また、 -v
オプションで詳細を表示できます。
1 | $ ./entropy -v file.txt |
ファイルサイズ * エントロピー で圧縮の下限値を計算することができます。
上記の場合は3バイトよりも圧縮することはできないということです。
ただし、この結果は無記憶情報源モデルの場合であり、モデル化によってエントロピーの値は異なることに注意してください。エントロピーをより小さくするモデルを作成することがでれきば、これよりも高い圧縮率を達成することができます。
以下のような文字列(ファイルに保存されているとする)からsedやawkを使ってlabelだけとるshell芸を紹介します。
1 | +-------------------------+-------+ |
1 | ⇒ sed -n '4,14p' table.txt | awk '{print $2}' |
1 | ⇒ sed -n '4,14p' table.txt | awk '{print $2 " "}' | tr -d '\n' |
sed -n '4,14p’
で指定した行数のみ取得しています
次にawk '{print $2}’
でlabel列のみ抽出しています。
改行を消すのは tr -d '\n’
が便利です。