http://jp.rubyist.net/magazine/?0011-CodeReview#l41
Rubyist Magazine - あなたの Ruby コードを添削します 【第 2 回】 HexStruct.rb
こちらに応募されるといいのではないでしょうか。
というだけではナンなので、たいしたことは言えませんが少しだけ書いてみます。
print cmd + ”¥n”
は、
puts cmd
と書けます。
@@badHosts = Hash.new
は
@@badHosts = Hash.new {|hash, key| hash[key] = 0 }
とする(デフォルト値を指定する)ことで、25行目からの
if @@badHosts[host] then
@@badHosts[host] += 1
else
@@badHosts[host] = 1
end
を、
@@badHosts[host] += 1
だけにできます。
45行目からの
x_month = m[1]
x_date = m[2]
x_time = m[3]
……は、
x_all, x_month, x_date, x_time, …… = m
と多重代入できます。……が、これは元のままの方が見やすいですかね。
56行目からの判定部分は同様の処理が連続しているので
[
# Invalid user bgray from ::ffff:82.85.1.1
[x_arg, /^Invalid user .* from (::ffff:)?([-.0-9A-Za-z]+)/, 2],
# User root from 10.10.10.10 not allowed because not listed in AllowUsers
[x_arg, /^User .* from (::ffff:)?([-.0-9A-Za-z]+) not allowed/, 2],
# Did not receive identification string from ::ffff:164.125.1.1
[x_arg, /^Did not receive identification string from (::ffff:)?([-.0-9A-Za-z]+)/, 2],
].each{|arg, re, n|
next if arg !~ re
addBad Regexp.last_match[n]
}
などと、まとめてしまうと良いかも。
もう少し汎用的には
[
# Invalid user bgray from ::ffff:82.85.1.1
proc{
x_arg =~ /^Invalid user .* from (::ffff:)?([-.0-9A-Za-z]+)/ ? $2 : nil
},
# User root from 10.10.10.10 not allowed because not listed in AllowUsers
proc{
x_arg =~ /^User .* from (::ffff:)?([-.0-9A-Za-z]+) not allowed/ ? $2 : nil
},
# Did not receive identification string from ::ffff:164.125.1.1
proc{
x_arg =~ /^Did not receive identification string from (::ffff:)?([-.0-9A-Za-z]+)/ ? $2 : nil
},
].each{|pr|
x_badhost = pr.call
addBad(x_badhost) if x_badhost
}
という感じでしょうか。
http://www.ruby-lang.org/ja/man/
Rubyリファレンスマニュアル - Rubyリファレンスマニュアル
class Observation
def Observation.start(arg)
Observation.new.start(arg)
end
def initialize
@blacklist = Hash.new{|hash,key| hash[key] = 0}
@judgement = 10
end
def start(target)
pipe = IO.popen(”tail -f #{target}”,’r’)
loop do
if (input = pipe.gets)
result = analyze(input)
if result[’protocol’] =~ /ssh/ && result[’success?’] == false
add_black(result[’ip’])
end
add_deny(result[’ip’]) if @blacklist[result[’ip’]] > @judgement
end
end
end
def analyze(str)
flag = true
ary = str.split
date = ary.slice!(0..2).join(’ ’)
host = ary.shift
protocol = ary.shift
if pos = ary.index(’from’)
ip = ary.slice!(pos + 1)
end
flag = false if ary.include?(’not’||’invalid’)
return {’date’ => ”#{date}”, ’host’ => ”#{host}”, ’protocol’ => ”#{protocol}”,
’ip’ => ”#{ip}”, ’success?’ => ”#{flag}”}
end
def add_black(ip)
@blacklist[ip] += 1
end
def add_deny(ip)
file = File.open(”/etc/hosts.deny”,’a+’)
file.flock(File::LOCK_EX)
file.puts(ip)
file.flock(File::LOCK_UN)
file.close
end
end
if $0 == __FILE__
Observation.start(’/var/log/messages’)
end
Rubyっぽくってことでこんな感じでどうでしょう?
急ごしらえなんで実用レベルのものではないですけど。
なるほど。1)まずはClassを作り、2)コマンドラインから呼び出された場合はif $0==__FILE__で処理する というのがRubyっぽい構造に見えますね。Class内部もRubyっぽくてステキです
Hashのデフォルト値というのは、こうやって使うんですね!「いったい何に使うんだろう」と思っていました。ありがとうございます。