2013年6月28日金曜日

cut コマンドでCSV/TSVの特定のカラム情報のみを抽出する

http://linuxjm.sourceforge.jp/html/GNU_textutils/man1/cut.1.html

CSVやTSVが手元にある時、ある特定のカラムの情報だけを抜き出したい場合、cutコマンドを使用するのが便利そうです。
$ vi hoge.csv
a,b,c
1,2,3
4,5,6
7,8,9
というCSVがあった時に、カラム"b"だけを抜き出したい場合は
$ cut -d "," -f 2 hoge.csv
b
2
5
8
という感じで抜き出せます。

"-d" はデリミタで、デフォルトはタブ区切り文字です。TSVの場合は-dは未指定でも可。
"-f"は抜き出すカラム(一番左が1)。複数抜き出す場合は"2,3"のようにカンマ区切りで複数指定すればOKです。

2013年6月25日火曜日

mac に jq(command-line JSON Prosesser) をインストールする

ここからダウンロードするのが一番ラクだということに気づいた…
http://stedolan.github.io/jq/

ダウンロード後、実行パーミッション(chmod +x )を加えればOKです。

Fluentd + out_s3 でタグごとに出力先フォルダを変更する

勿論タグごとに match エレメントを記載してベタ書きしても良いのですが、こういう際は、複数の設定を動的に行えるforest pluginが便利です。

https://github.com/tagomoris/fluent-plugin-forest

◯設定例
<match hoge.**>
    type forest
    subtype s3
    <template>
        aws_key_id [aws_key]
        aws_sec_key [secret_key]
        s3_bucket [bucket_name]
        s3_endpoint [region_name].amazonaws.com
        path fluentd_logs/${tag}/
        buffer_path /var/log/fluentd/${tag}
    </template>
</match>
データの保存先(path ならびに buffer_path)にplace holderとして${tag}を指定しています。
このように設定しておくと、"hoge.**"  のログデータについてタグごとに fluentd_logs/ 配下に保存されるようになります。

一点注意として、out_s3はfile typeのbufferを標準では使用するようになっており、いったんバッファ情報を特定フォルダ(buffer_path)に保存します。その際、buffer_path の保存先をタグごとに振り分けて置かないと、同じbufferファイルに複数タグのデータが保存され、S3保存時にも一緒くたに保存されてしまいます。


◯json内に含まれた値に応じて保存先を変更する
あらかじめ設定されたタグではなく、jsonに含まれた値に応じて保存先を変更したい場合は、rewrite_tag_filter を使用してタグを書き換える、という方法があります。
https://github.com/y-ken/fluent-plugin-rewrite-tag-filter

たとえばFluentdに流れているデータが以下のようなフォーマットになっていて、
1970-01-01T00:00:00+09:00   log.pc    {"event":"register"}
"event" に各種イベント名が含まれており、タグ名とイベント名の組み合わせごとに保存先を変更したい、という場合は以下のように設定します。
<match log.**>
    type forest
    subtype rewrite_tag_filter
    <template>
        remove_tag_prefix log
        capitalize_regex_backreference yes
        rewriterule1 event (.*) hoge.${tag}_$1
    </template>
</match>
log.pc というタグを hoge.pc_register というタグに書き換えています。
こちらと先述のout_s3の定義を組み合わせると、最終的に [bucket_name]/fluentd_logs/hoge.pc_register/ というS3のディレクトリにファイルが保存されます。


s3 の Reduced Redundancy Storage に書き込む

S3に多少のロストが許容できるようなそれほど重要でない情報を少し安く保存する、という手段として、Reduced Redundancy Storage(RSS)として書き込む、という方法があります。

以下は3年前のブログなので、改めて触れるまでも無く大多数の方はご存知でしょうが…
http://aws.typepad.com/aws/2010/05/new-amazon-s3-reduced-redundancy-storage-rrs.html

ノーマルオプション(Standard)では 99.999999999% の可用性が保証されているのに対し、RSSオプションでは 99.99% の可用性で、もし10,000ファイルをS3に置いた場合、1年の間に1つかそれ以上のファイルがロストする、という計算。ただしその分価格が33%割安、となります。
あまり長期保存しないファイルを一時的に置く、万が一ロストしても構わない、という場合RSSを選択するとかなりお得になります。


◯rubyのaws-sdkでreduced_redundancyを有効にする
http://aws.amazon.com/jp/sdkforruby/
require 'aws-sdk'

s3 = AWS::S3.new({})
bucket = s3.buckets[s3_bucket]
bucket.objects[s3path].write(Pathname.new(filepath), :reduced_redundancy => true)

◯pythonのaws-sdkでreduced_redundancyを有効にする
http://aws.amazon.com/sdkforpython/
import boto

s3 = boto.connect_s3()
bucket = s3.lookup(s3_bucket)
key = bucket.new_key(s3path)
key.set_contents_from_filename(filepath, reduced_redundancy=True)

◯Fluentdのout_s3でreduced_redundancyを有効にする。
現バージョン(2013/6/25現在)ではreduced_redundancyに対応していないので、以下のような修正を行う必要があります。
https://github.com/moaikids/fluent-plugin-s3/commit/183708f6a9a5c2eb12e8d64a9f02233c25cb3a9d

2013年6月24日月曜日

mrjob で手軽に elastic map reduce

http://pythonhosted.org/mrjob/

mrjobは、AWSのElastic MapReduceサービスを手軽に使用するためのPython実装です。
EMRのクライアントライブラリとして有名な"Amazon Elastic MapReduce Ruby Client( http://aws.amazon.com/developertools/2264 ) "と比べると出来ることは少ない印象ですが、その分シンプルに使うことができます。


◯インストール
pip install mrjob

◯jobの作成
mrjobに含まれている"MRJob" というクラスを継承することで、手軽にmapper / reducerのjob作成する事ができます。以下はmrjobのサイトにも記載されている、word countを行うサンプルのソース。
#mrjob_sample.py
from mrjob.job import MRJob


class MRWordCounter(MRJob):

    def mapper(self, key, line):
        for word in line.split():
            yield word, 1

    def reducer(self, word, occurrences):
        yield word, sum(occurrences)


if __name__ == '__main__':
    MRWordCounter.run()

◯ローカル環境で実行
ローカル環境で作成したjobの動作確認ができます。
python mrjob_sample.py test.txt > result.txt
test.txtの中身が以下のようなものだった場合
A job consists of an MRJob subclass, one or more mapper, combiner, or reducer methods, a call at the bottom to invoke mrj    ob’s logic, and all associated dependencies.
For jobs that consist only of one mapper, combiner, and reducer, in that order, you can simply override one or more of th    e mapper(), combiner(), and reducer() methods:
MapReduceの実行結果が出力されたresult.txtの中身は以下のようになります。
"A" 1
"For"   1
"MRJob" 1
"a" 1
"all"   1
"an"    1
"and"   3
"associated"    1
"at"    1
"bottom"    1
(snip.)

◯EMRの設定
EMRの環境でjobを実行するには、設定ファイルを作成する必要があります。
この中でAWSのcertificate情報や、起動するインスタンスの種類などを指定します。
以下は最低限動作させるための一例です。詳しくは公式サイトのドキュメントを参考ください。
http://pythonhosted.org/mrjob/guides/quickstart.html#configuration
#emr.conf
runners:
    emr:
        aws_access_key_id: [access_key_id]
        aws_region: [region]
        aws_secret_access_key: [secret_access_key]
        ec2_instance_type: m1.small
        num_ec2_instances: 3
        cmdenv:
        s3_log_uri: s3://[bucket_name]/emr/logs/

◯EMR環境で実行
emr環境で実行する場合は" -r emr" オプションを指定します。また、解析対象のデータのs3のパスを指定します。
python mrjob_sample.py -r emr --conf-path ./emr.conf s3://[bucket_name]/[file_path] > result.txt

◯バグ?
実は、pip installでmrjobをダウンロードした場合、上記の手順では正常にEMR上で動作させる事ができませんでした。
ローカル実行は可能ですが、EMR上で動作させる際に"returned an invalid certificate"というエラーメッセージが表示し、emrのエンドポイントへの接続が正しく行われませんでした。

同様のエラーが以下issueに報告されていますが、現在は未だ修正が行われていないようです。
https://github.com/Yelp/mrjob/issues/621

上記issueにも記載されているように、mrjobのemr.py中に記載されているEMRのendpoint URLを
    #'ap-northeast-1': 'elasticmapreduce.ap-northeast-1.amazonaws.com',
    'ap-northeast-1': 'ap-northeast-1.elasticmapreduce.amazonaws.com',
という形で書き換えてあげると、うまく動作するようになります。



mrjobはシンプルとはいえ、色々な記述方法、設定方法があり、各種管理コマンドも用意されているようなので、以降も気が向いたら記事を書いていこうと思います。




2013年6月20日木曜日

あるページがfacebookで"いいね""シェア"をされている数を取得

メモ。一番簡単なのは以下。ただし"いいね"と"シェア"の合算値なのかなんだかよく分からない"shares"という値だけが返ってくる。
curl http://graph.facebook.com/http://itsneatlife.blogspot.jp/


jetty の出力するアクセスログをカスタマイズする

かなりjetty独自の方法になっていたのでメモ。

基本的には、${JETTY_HOME}/etc/jetty-requestlog.xml を編集することで行います。
なお、以下は一般的なログ形式であるNCSAに準拠した”NCSARequestLog”を使用した例です。

  • filename : 出力するログファイル名。デフォルトでは"yyyy_mm_dd.request.log"という形で保存されdaily rotateされます。
  • filenameDateFormat : ログファイルに含める日付表現のフォーマット
  • retainDays : 何日間保存するか。デフォルトでは90日
  • extended : trueにするとcombined方式で出力されます。デフォルトはfalse(common)
  • logDateFormat : ログの日付領域の日付表現
  • logLocale : 出力ログのロケールの設定。
  • LogTimeZone : 出力ログのタイムゾーンの設定。デフォルトはGMT
他にも設定項目は多種ありますが、それらしきドキュメントに辿りつけなかったので、直接ソースやJavadocを参照するのが良いと思います。