最近、また ruby を使っています。自宅ではなく、派遣先でのことです。
やることはテキストファイルの加工なんで、別に、awk でも、perl でも、なんなら php でもいいでんですが、書きやすいという点ではやっぱり ruby が一番という気がしてます。
今やっているのは、httpd のログファイルの解析。
世の中には、httpd のログを解析する仕組みはいくらでもあるのですが、できるだけ元のデータ
が見たいなと思う。しかも、必要な箇所だけ表示したり、集計したりすると Excel に読めれば
ベスト、と思っているので、Excel に読めるようにCSVファイルになっていると都合がいい。
最初から httpd のログをそんな風に出力できれば問題ないのだろうが、なかなか勝手にいじる
訳にもいかない、となると、デフォルトの形式で出力されたログファイルを、Excel で読みやすいように加工しようか、ということに。
昔は、ruby でなんて考えられないくらい CPU が遅かったので、こういうのはちゃんとCで書いたものだ。しかし、最近は CPU が早いので ruby でもやれてしまう。いい時代になったな…
今回作成したのは、こんな感じのスクリプトです。
#!/usr/bin/ruby # def explode_word( string ) start_p = @current_pos if start_p >= string.length then return false end key = string[start_p, 1] if key.eql?("[") then e_pos = string.index("]", start_p) +1 elsif key.eql?("\"") then e_pos = string.index("\"", start_p+1) +1 else e_pos = string.index(" ", start_p) end ret_s = string[start_p, (e_pos - start_p)] @current_pos = e_pos+1; return( ret_s ) end # filename = "access_log" words = Array.new logs_ip = Array.new logs_date = Array.new logs_hour = Array.new logs_url = Array.new logs_stat = Array.new logs_agent = Array.new if( fp = open( filename, "r") ) then fp.each_line do |line| tmp = line.chop @current_pos = 0 i=0 while( (words[i] = explode_word(tmp) ) != false ) do i=i+1 end date_s = words[3][1,11] hour_s = words[3][13,2] logs_date[log_count] = date_s logs_hour[log_count] = hour_s # access url logs_url[log_count] = words[4] # status ( ex. 200 401 404 ) logs_stat[log_count] = words[5] # access agent logs_agent[log_count] = words[8] # log_count = log_count +1 end fp.close end # # for status = 404 # wfp = open("404.log", "w") i=0 while( i < log_count ) do if logs_stat[i].to_i == 404 then wfp.write( logs_ip[i]+ "," ) wfp.write( logs_date[i]+ "," ) wfp.write( logs_hour[i]+ "," ) wfp.write( logs_url[i]+ "," ) wfp.write( logs_stat[i]+ "," ) wfp.write( logs_agent[i]+ "\n" ) end i=i+1 end
1行に出力されている各項目を切り出して、一旦配列に入れ、そこから Excel で使いたいデータにしてCSVで出力しています。当初はステータス毎にファイルに書き出そうかと思ったのですが、結局データが多すぎるので、404(ファイルが存在しない)に注目して今回は確認を行いました。それでも、結構出ています。
ブログの記事は、それぞれ担当者が書いており、テクのある人は自分でテーマを作ったりしている(作ってもらっている?)ようです。前任者はサーバーを設定すれば終わり、という管理者だったようで、抜けが結構ありました。まあ、自作したテーマのミス?というのもあり、この辺はログを見れる人でないと解らないかも、というのも。
サーバーが安定して稼動してくれればいいのですが、エラーがたくさん出ている状況は管理者としては気分がよくないし。整理できてよかったかも。
同じように error_log でも同じように作ってみました。
#!/usr/bin/ruby # def explode_word( string ) start_p = @current_pos if start_p >= string.length then return false end key = string[start_p, 1] if key.eql?("[") then e_pos = string.index("]", start_p) +1 else e_pos = string.length() end ret_s = string[start_p, (e_pos - start_p)] @current_pos = e_pos+1; return( ret_s ) end filename = "blog.tuad.ac.jp-error_log.1" #filename = "err1000.log" words = Array.new logs_date = Array.new logs_stat = Array.new logs_cli = Array.new logs_msg = Array.new @current_pos = 0 log_count = 0 if( fp = open( filename, "r" ) ) then fp.each_line do |line| tmp = line.chop @current_pos = 0 i=0 while( (words[i] = explode_word(tmp)) != false ) do i=i+1 end logs_date[log_count] = words[0] logs_stat[log_count] = words[1] if words[3] == false then logs_cli[log_count] = "[-]" logs_msg[log_count] = words[2] else logs_cli[log_count] = words[2] logs_msg[log_count] = words[3] end log_count = log_count +1 end fp.close end if log_count > 0 then wfh = open("err.log", "w") i=0 while( i < log_count ) do wfh.write( logs_date[i].to_s + "," ) wfh.write( logs_stat[i].to_s + "," ) wfh.write( logs_cli[i].to_s + "," ) wfh.write( logs_msg[i].to_s + "\n" ) i=i+1 end end
こういうので調べると実は知らなかったことがあり、今時のサーバー管理が学べます。
来週、今回手を入れた箇所がちゃんと動いているのを確認する予定。
そこで、また、何か発見があるかも、とちょっとワクワクしてます。