#!/usr/bin/ruby # # smart-track.rb # written by antonone_ # # visit http://anadoxin.org/blog # require 'date' $disks = { :home => "/dev/sda", :win7 => "/dev/sdb", :system => "/dev/sdc" }; $confdir = "/var/log/smart-track" $infos = [] class SmartInfo attr_accessor(:bad_blocks, :temp, :dev, :caption, :pending) def to_s() "%s,%s,%d,%d,%d" % [ @dev, @caption, @bad_blocks, @temp, @pending ] end end def read_smart(devices, symbol) info = SmartInfo.new() device = devices[symbol] info.dev = device info.caption = symbol.to_s `smartctl -a #{device}`.each() do |line| info.bad_blocks = $2.to_i if(line =~ /(\d+) Reallocated_Sector_Ct.*-[ ]+(\d+)/i && $1.to_i() == 5) info.temp = $2.to_i if(line =~ /(\d+) Temperature_Celsius.*-[ ]+(\d+)/i && $1.to_i() == 194) info.pending = $2.to_i if(line =~ /(\d+) Current_Pending_Sector.*-[ ]+(\d+)/i && $1.to_i() == 197) end return(info) end def lock(name) 1.times() do if(File.exists?("#{$confdir}/.lock_#{name}")) sleep(1) redo else File.open("#{$confdir}/.lock_#{name}", "w") do |fp| fp.write("locked") end end end end def unlock(name) File.unlink("#{$confdir}/.lock_#{name}") rescue end def get_last_state() IO.readlines("#{$confdir}/last_state").join().to_i rescue Errno::ENOENT return 0 end def put_last_state(last_state) File.open("#{$confdir}/last_state", "w") do |fp| fp.write(last_state) end end def save_state(infos) last_state = get_last_state() last_state += 1 File.open("#{$confdir}/state_%05d" % [ last_state ], "w") do |fp| infos.each() do |info| fp.write("#{info}\n") end end put_last_state(last_state) end def load_prev_info() last_state = get_last_state() infos = [] IO.readlines("#{$confdir}/state_%05d" % [ last_state ]).each() do |line| info = SmartInfo.new() info.dev,info.caption,info.bad_blocks,info.temp,info.pending = line.split(',').map() do |i| i.strip() end info.bad_blocks = info.bad_blocks.to_i info.temp = info.temp.to_i info.pending = info.pending.to_i infos << info end return infos rescue Errno::ENOENT return infos end begin lock("glob") prev_infos = load_prev_info() $disks.each() do |key,value| info = read_smart($disks, key) $infos << info prev_infos.each() do |prev_info| if(prev_info.dev == info.dev) if(info.bad_blocks > prev_info.bad_blocks) `/home/antek/bin/sms self "Uwaga, zwiekszona ilosc bad blockow na dysku #{info.dev} - wczesniej: #{prev_info.bad_blocks}, teraz: #{info.bad_blocks}."` end if(info.pending > prev_info.pending) `/home/antek/bin/sms self "Uwaga, zwiekszona ilosc pending sectors na dysku #{info.dev} - wczesniej: #{prev_info.pending}, teraz: #{info.pending}."` end end end end save_state($infos) unlock("glob") rescue unlock("glob") end