Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
280
Help us understand the problem. What is going on with this article?
@richmikan@github

たった6個のsedを通せば、Apacheログは驚くほど扱いやすくなる

More than 3 years have passed since last update.

Q. awk '{print $9}'とかでUser-Agent丸ごと取り出したい

とか思ったことない? Apacheのログ解析で。でもできないじゃない。例えば

combined形式ログ
192.168.0.1 - - [17/Apr/2014:11:22:33 +0900] "GET /index.html HTTP/1.1" 200 43206 "https://www.google.co.jp/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36"

なんかのログで"mozilla/5.0 (Windows NT 6.1 …… Safari/537.36"の部分が欲しいなーと思って、AWKで取ろうとしても

こーなってしまう
$ awk '{print $12}' httpd-access.log
"Mozilla/5.0
$ 

なーんてふうに、最初のスペースまでで切れてしまって全然使い物にならない。さて、何とかならないものか。

A. 6個のsedコマンドにパイプで通せばできるよ

でも、そこは我らがUNIX。シェルスクリプトとパイプと標準コマンドさえあればお手のもの。sedコマンド6個通すだけでできるようになるのさ。

次のシェルスクリプトを書いてこいつに流し込むだけ。
(2014/05/05) おい、動かねーじゃねーか!という指摘を受けて修正しました。m(_ _;)m

apalognorm.sh(Apachログを整形するシェルスクリプト)
#! /bin/sh

# ----- ちょいと下ごしらえ -----
RS=$(printf '\036')             # 元々の改行位置にマークするための記号定義
LF=$(printf '\\\n_');LF=${LF%_} # sedで改行コードを挿れるための定義

# ----- 本番 -----
sed 's/^\(.*\)$/\1'"$RS"'/'                |
sed 's/"\([^"]*\)"/'"$LF"'"\1"'"$LF"'/g'   |
sed 's/\[\([^]]*\)\]/'"$LF"'[\1]'"$LF"'/g' |
sed '/^["[]/s/[[:blank:]]/_/g'             | # ここに空白の代替文字
sed 'N;$s/\n//g'                           |
sed 's/'"$RS"'/'"$LF"'/g'

試しに実行してみると、

ほらこのとおり
$ cat httpd-access.log | apalognorm.sh
192.168.0.1 - - [17/Apr/2014:11:22:33_+0900] "GET_/index.html_HTTP/1.1" 200 43206 "https://www.google.co.jp/" "Mozilla/5.0_(Windows_NT_6.1;_WOW64)_AppleWebKit/537.36_(KHTML,_like_Gecko)_Chrome/34.0.1847.116_Safari/537.36"
$ 

日時列(4列目)、HTTPリクエストパラメーター列(5列目)、User-Agent列(9列目)に含まれているスペースが全て_に置換されている。もちろん、列を区切っているスペースはそのままで。

もし、_が気に食わないのであれば*でも+でも、好きな文字列(2文字以上でもいい)を4番目のsedの後半部分に書けばいいだけ。

6つのsedは何をやってるのか?

sed 1号

(加工の都合により、途中で一時的に改行を挿むので)元の改行を別の文字(0x1e)で退避させておく。

sed 2号

ダブルクォーテーションで囲まれている区間"~"があったら、その前後に改行を挿み、その区間を単独の行にする。

sed 3号

ブラケットで囲まれいる区間[~]も同様に、前後に改行を挿んで、この区間を単独の行にする。

sed 4号

ダブルクォーテーション、またはブラケットで始まる行は、先程行を独立させた区間なので、これらの行にある空白をそうでない文字列に置換する。

sed 5号

改行を全部取り除く。(これはべつにsedでやる必要ないのだけど)

sed 6号

退避させていた元々の改行を復活させる。(これもべつにsedでやる必要ないのだけど)

コマンド化したものをGitHubに置いておいたよ

例によってちゃんとコマンド化したものをGistに上げておいた。ログ解析で困っているなら使ってみてね。スペースの代替文字が_では気に入らない人向けに、オプションで指定できるよにしてある本格派だ。

Apacheサーバー管理者は、これで少し幸せになれるかも。

尚、Gistに上げたものは、5号と6号のsedはtrに置き換えているので悪しからず。まぁ、全部sedでやるというのはネタだからねぇ。

280
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
richmikan@github
困った時はすぐQiitaを始めとしたTipsを表面的に鵜呑みにし、使えそうなプロダクトを拾ってきてマニュアル通りに対応するプロダクト至上主義者達よ。そんなことでは、想定外の事態に見舞われた時すぐ死ぬぞ。想定外とは、マニュアルには載ってないから想定外なのだ。マニュアル通りにしか動けぬ者は、典型的なコンビニ店員の如く薄給に喘ぐだけ。頭を使え!UNIX哲学に目覚めよ!そしてPOSIX原理主義を崇拝せよ!

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
280
Help us understand the problem. What is going on with this article?