ラベル Ruby の投稿を表示しています。 すべての投稿を表示
ラベル Ruby の投稿を表示しています。 すべての投稿を表示

月曜日, 9月 06, 2010

Rubyでログファイルを定期的に監視

2008/04/03perlfreak.vox.comより転載)

RubyGemsでtmailをインストールしてある前提。
ログファイルには指定するキーワードの他にサイトIDが出力されている前提。
これを5分おきに実行。

=== ( log_check.rb ここから) ===
#!/usr/bin/env ruby

require 'rubygems'
require 'tmail'
require 'iconv'
require 'net/smtp'

# ホスト名
host = `/bin/hostname`.chomp

# ログファイル
log_file = '/var/log/hoge.log'

# フラグ用ディレクトリ
flag_dir = '/var/run/log_check/'

# キーワード
log_keyword = '混雑'

# チェック間隔(秒)
interval = 300

# アラートまでのチェック回数
alert_check_count = 3

# 送信先
mailto = [
'foo@bar.com'
]

## prefix作成メソッド
def make_prefix( num )
return "_" + num.to_s + "_"
end

## ディレクトリ下ファイル名からのサイトID取得メソッド
def get_flag_site_list( dir_path, prefix_num )
prefix = make_prefix( prefix_num )
site_id_ary = Array.new
file_path_ary = Dir.glob( dir_path + "#{prefix}*" )
file_path_ary.each do |file_path|
/^#{prefix}(.+)$/ =~ File.split( file_path )[1]
site_id_ary.push( $1 )
end

return site_id_ary
end

## ログファイルからキーワードを含む行のサイトID取得メソッド
def get_log_site_list( sec, keyword )
site_id_ary = Array.new
boundary_time = (Time.now - sec).strftime( "[%Y/%m/%d %H:%M:%S]" )
tail_lines = sec * 50
grep_result = `/usr/bin/tail -#{tail_lines} #{log_file} | /bin/grep "#{keyword}"`
grep_result.split( /\n/ ).each do |line|
line_ary = line.split( /\s+/ )
site_id = line_ary[3]
time_stamp = line_ary[0] + ' ' + line_ary[1]
if time_stamp >= boundary_time
if !site_id_ary.include?( site_id )
site_id_ary.push( site_id )
end
end
end

return site_id_ary
end

## メール送信メソッド
def send_mail( mailto, host, site_id, alt )
subject = "混雑リカバリ (" + site_id + ")"
if alt == "alert"
subject = "混雑アラート (" + site_id + ")"
end

from = 'system@bar.com'
mesg = host + "\n\n" + site_id

mail = TMail::Mail.new
mail.to = mailto
mail.cc = ['']
mail.bcc = ['']
mail.from = from
mail.subject = Iconv.conv( 'ISO-2022-JP', 'EUC-JP', subject )
mail.date = Time.now
mail.mime_version = '1.0'
mail.set_content_type( 'text', 'plain', {'charset' => 'iso-2022-jp'} )
mail.encoding = '7bit'
mail.body = Iconv.conv( 'ISO-2022-JP', 'EUC-JP', mesg )

Net::SMTP.start( 'localhost', 25 ) do |smtp|
str = mail.encoded
smtp.send_mail( str, mail.from, mail.destinations )
end
end

# ログファイルからサイトID取得
busy_site_ary = get_log_site_list( interval, log_keyword )

# フラグファイル名からサイトID取得
flag_site_arys = Array.new
count = 1
while count <= alert_check_count flag_site_arys.push( get_flag_site_list( flag_dir, count ) ) count += 1 end

# 初期フラグ
first_flag_ary = busy_site_ary
flag_site_arys.each do |site_ary|
first_flag_ary = first_flag_ary - site_ary
end
prefix = make_prefix( 1 )
first_flag_ary.each do |site_id|
flag_file = flag_dir + prefix + site_id
system( '/bin/touch', flag_file )
if alert_check_count == 1
send_mail( mailto, host, site_id, "alert" )
end
end

# フラグ変更(削除)&メール送信
count = 1
flag_site_arys.each do |site_ary|
prefix = make_prefix( count )
if count < prefix_2 =" make_prefix(" flag_file =" flag_dir" flag_file_2 =" flag_dir" count ="="" flag_file =" flag_dir" count ="="" end ="="="">

RubyでWebサイトのレスポンス監視

2008/02/25perlfreak.vox.comより転載)

RubyGemsでtmailとmechanizeをインストールしてある前提。
これをcronで5分おきに実行。

=== ( response_check.rb ここから ) ===
#!/usr/bin/env ruby

require 'rubygems'
require 'tmail'
require 'iconv'
require 'net/smtp'
require 'mechanize'

# アラートフラグ用ディレクトリ
alert_dir_path = '/var/run/response_check/'

# アラートまでのチェック回数
alert_check_count = 2

# チェック対象
target_hash = {
'www_hoge_jp' => {
'url' => 'https://www.hoge.jp/',
'user_id' => 'foo',
'password' => 'bar',
'mailto' => [ 'list@hoge.com' ],
'alert_time' => 3
},
'www2_hoge_jp' => {
'url' => 'https://www2.hoge.jp/',
'user_id' => 'foo',
'password' => 'bar',
'mailto' => [ 'list@hoge.com' ],
'alert_time' => 3
},
'www3_hoge_jp' => {
'url' => 'https://www3.hoge.jp/',
'user_id' => 'foo',
'password' => 'bar',
'mailto' => [ 'list@hoge.com' ],
'alert_time' => 3
}
}

## ログインしてから管理画面が表示されるまでの時間を返すメソッド
def response_time( user_agent, url, user_id, password )
agent = user_agent
page = agent.get( url )
form = page.forms.with.name( 'login' ).first
form.userid = user_id
form.password = password
start_time = Time.now.to_f
results = agent.submit( form )
body = results.body
end_time = Time.now.to_f

return end_time - start_time
end

## メール送信メソッド
def mail_send( target, url, mailto, response, alt )
subject = ""
if alt == "alert"
subject = "応答時間アラート (" + target + ")"
else
subject = "応答時間リカバリ (" + target + ")"
end

mesg = target + "\n\n" + "応答時間:" + "#{response}"

mail = TMail::Mail.new
mail.to = mailto
mail.cc = ['']
mail.bcc = ['']
mail.from = 'system@hoge.jp'
mail.subject = Iconv.conv( 'ISO-2022-JP', 'EUC-JP', subject )
mail.date = Time.now
mail.mime_version = '1.0'
mail.set_content_type( 'text', 'plain', {'charset' => 'iso-2022-jp'} )
mail.encoding = '7bit'
mail.body = Iconv.conv( 'ISO-2022-JP', 'EUC-JP', mesg )

Net::SMTP.start( 'localhost', 25 ) do |smtp|
str = mail.encoded
smtp.send_mail( str, mail.from, mail.destinations )
end
end

# アラートメール、リカバリメール
agent = WWW::Mechanize.new
target_hash.each do | key, value |
flag_file_ary = Dir.glob( alert_dir_path + "#{key}_[1-9]*" )
url = value['url']
user_id = value['user_id']
password = value['password']
mailto = value['mailto']
alert_time = value['alert_time']
response = response_time( agent, url, user_id, password )

if flag_file_ary.size == 0
if response > alert_time
system( '/bin/touch', alert_dir_path + key + "_1" )
if alert_check_count == 1
send_mail( key, mailto, response, "alert" )
end
end
elsif flag_file_ary.size == 1
flag_file = flag_file_ary[0]
/^#{key}_([\d]+)$/ =~ File.split( flag_file )[1]
flag_count = $1.to_i
if response > alert_time
if flag_count < flag_file_2 =" alert_dir_path" flag_count ="="" flag_count ="="" end ="="="">

Exerb(Rubyスクリプトをexeファイルに)

2007/01/16perlfreak.vox.comより転載)

RubyスクリプトをWindowsのexeファイルにしてくれるExerbなるものがある。
まず、Cygwin環境でインストール。

$ unzip exerb-4.1.0.zip
$ cd exerb-4.1.0
$ ruby setup.rb

以下は、CSVファイルの行を指定された項目でソートし、項目の入れ替えを行なうサンプル。
ファイルは、convert.rb、sort-array.rb、convert.confの3つ。

=== (convert.rb ここから) ===
#!/usr/bin/ruby

require "csv"
require "sort-array"

print "Now working..."

array_file = ARGV

if array_file

array_file.each do |file_name|

if FileTest.size?(file_name) && /(.*)\.csv$/i =~ file_name
to_file = $1 + '_new.csv'
array_input = Array.new

CSV.open(file_name, 'rb') do |row|
array_input <<>

array_output = SortArray.new.convert(array_input)

File.open(to_file, 'wb') do |output|

array_output.each do |array_line|
line = ""

array_line.each do |item|

if line.size == 0
line = item
else
line = line + ',' + item
end
end

line = line + "\r\n"
output.write(line)
end
end
end
end
end

exit
=== (convert.rb ここまで) ===

=== (sort-array.rb ここから) ===
class SortArray
# 設定ファイルの内容を取得してハッシュで返す
def get_conf
conf_file = "convert.conf"
hash_conf = Hash.new

if defined? ExerbRuntime
conf_file = File.dirname(ExerbRuntime.filepath) + "/" + conf_file
end

File.readlines(conf_file).each do |line|
line = line.sub(/(?:\r|\r\n|\n)\z/, "")

if /\a\s*(.*)\s*:\s*(.*)\s*\z/ =~ line
hash_conf["$1"] = "$2"
end
end

return hash_conf
end

# 引数の配列の要素を設定によって並べ替えて返す
def convert(array_input)
@array_input = array_input
hash_conf = self.get_conf
array_keys = Array.new
array_result = Array.new

hash_conf.each do |key,value|
if key == "sort_key"
array_keys = value.split(/\s*,\s*/)
end
end

array_result = @array_input.sort{|y,x| \
[x[array_keys[0].to_i],x[array_keys[1].to_i],x[array_keys[2].to_i]] \
<=> [y[array_keys[0].to_i],y[array_keys[1].to_i],y[array_keys[2].to_i]]}

array_result.each do |line_item|
line_item[1],line_item[2],line_item[3],line_item[4],line_item[5] \
= line_item[3],line_item[5],line_item[1],line_item[2],line_item[4]
end

return array_result
end
end
=== (sort-array.rb ここまで) ===

=== (convert.conf ここから) ===
sort_key:0,3,5
=== (convert.conf ここまで) ===

これらの準備ができたところで

$ mkexy convert.rb
$ exerb convert.exy

はい、これでconvert.exeのできあがり。
Windows上でconvert.exeに6項目以上からなるCSVファイルをドラッグ&ドロップすると、拡張子の前に_newがついた変換後のファイルが生成される。