TextDrive: Simple disk usage and HTTP bandwidth counts
Updated version from http://textsnippets.com/posts/show/632
This script will allow a TextDrive account holder to easily see their disk usage and monthly HTTP bandwidth consumption, until TextPanel provides the information.
The first time you use rsrcmeter, it may take additional time, as it will be scanning every Apache/HTTP log file for usage information and caching it by month.
--> Get Easy Install Instructions, Etc. at http://rsrcmeter.textjoy.com/.
Sample output:
Disk usage: 23.7227 MiB (Quota: 10.0000 GiB | 0.2% used)
Bandwidth:
Nov 2006: 0.5494 MiB (Month to Date)
Oct 2006: 0.5087 MiB
Sep 2006: 0.5523 MiB
Aug 2006: 1.1567 MiB
require 'date'
require 'optparse'
module RFC2822
EmailAddress = begin
alpha = "a-zA-Z"
digit = "0-9"
atext = "[#{alpha}#{digit}\!\#\$\%\&\'\*+\/\=\?\^\_\`\{\|\}\~\-]"
dot_atom_text = "#{atext}+([.]#{atext}*)*"
dot_atom = "#{dot_atom_text}"
qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]'
text = "[\\x01-\\x09\\x11\\x12\\x14-\\x7f]"
quoted_pair = "(\\x5c#{text})"
qcontent = "(?:#{qtext}|#{quoted_pair})"
quoted_string = "[\"]#{qcontent}+[\"]"
atom = "#{atext}+"
word = "(?:#{atom}|#{quoted_string})"
obs_local_part = "#{word}([.]#{word})*"
local_part = "(?:#{dot_atom}|#{quoted_string}|#{obs_local_part})"
no_ws_ctl = "\\x01-\\x08\\x11\\x12\\x14-\\x1f\\x7f"
dtext = "[#{no_ws_ctl}\\x21-\\x5a\\x5e-\\x7e]"
dcontent = "(?:#{dtext}|#{quoted_pair})"
domain_literal = "\\[#{dcontent}+\\]"
obs_domain = "#{atom}([.]#{atom})*"
domain = "(?:#{dot_atom}|#{domain_literal}|#{obs_domain})"
addr_spec = "#{local_part}\@#{domain}"
pattern = /^#{addr_spec}$/
end
end
opt = {
:base_dir => ENV['HOME'],
:stat_file => 'histstat',
:temp_file => 'temp-rsrcmeter-bwcalc',
:bw_months => 5
}
OptionParser.new do |opts|
opts.banner = "Unofficial TxD Disk & HTTP Bandwidth Usage Meter\nUsage: rsrcmeter [options]"
opts.on("-b", "--base BASE", "Change the base directory, defaults to user's $HOME", String) {|base|
if File.exists?(base)
opt[:base_dir] = base
else
raise(ArgumentError, "Directory (#{base}) specified with -b does not exist")
end
}
opts.on("--stat-file FILE", "Change default historical data file from '#{opt[:stat_file]}'", String) {|file|
opt[:stat_file] = file
}
opts.on("--temp-file FILE", "Change default temporary file from '#{opt[:temp_file]}'", String) {|file|
opt[:temp_file] = file
}
opts.on("-m NUM", "Number of months' bandwidth to show prior to current month (default: #{opt[:bw_months]})", Integer) {|mons|
opt[:bw_months] = mons if mons > 0
}
opts.on("-e", "--email ADDRESS", "E-mail results to ADDRESS *instead* of outputting to the screen", String) {|addr|
if RFC2822::EmailAddress =~ addr
opt[:email_to] = addr
else
raise(ArgumentError, "Invalid e-mail address provided to -e")
end
}
opts.on_tail("-h", "--help", "Show this message") do
puts opts
exit
end
end.parse!
Dir.chdir(opt[:base_dir])
File.delete(opt[:temp_file]) if File.exists?(opt[:temp_file])
if File.exists?(opt[:stat_file])
@stats = Array.new
lines = File.readlines(opt[:stat_file])
lines.each {|l| (@stats << [l.chomp.split(',')[0], l.chomp.split(',')[1].to_f]) unless (l.strip)[0,1] == '#'}
@stats.sort!
if Date.today.month == 1
pm_year = Date.today.year - 1
pm_month = 12
else
pm_year = Date.today.year
pm_month = Date.today.month - 1
end
stop_month = pm_year.to_s + (pm_month < 10 ? '0' : '') + pm_month.to_s
proc_year = @stats.last[0][0,4].to_i
proc_month = @stats.last[0][4,2].to_i
proc_year += 1 if proc_month == 12
proc_month = (proc_month == 12) ? 1 : proc_month + 1
proc_str = proc_year.to_s + (proc_month < 10 ? '0' : '') + proc_month.to_s
while proc_str <= stop_month
datestr = proc_str + "??"
File.delete(opt[:temp_file]) if File.exists?(opt[:temp_file])
`cat logs/access_log.
`cat domains/*/logs/access_log.
`zcat logs/access_log.
`zcat domains/*/logs/access_log.
month_usage = `cat
@stats << [proc_str, month_usage]
proc_year += 1 if proc_month == 12
proc_month = (proc_month == 12) ? 1 : proc_month + 1
proc_str = proc_year.to_s + (proc_month < 10 ? '0' : '') + proc_month.to_s
end
else
file_list = Array.new
Dir.foreach(opt[:base_dir] + "/logs") {|i| file_list << i if /^access_log.\d{8}/ =~ i}
if File.exists?(opt[:base_dir] + "/domains")
domains = Array.new
Dir.foreach(opt[:base_dir] + "/domains") {|dom| domains << dom if /^\w+\.\w+/ =~ dom}
domains.each {|dom| Dir.foreach(opt[:base_dir] + "/domains/" + dom + "/logs") {|i| file_list << i if /^access_log.\d{8}/ =~ i}}
end
file_list.sort!
unless Date.today.year.to_s + Date.today.month.to_s == file_list.first[11,6]
earliest_log_year = file_list.first[11,4]
earliest_log_month = file_list.first[15,2]
@stats = Array.new
earliest_log_year.to_i.upto(Date.today.year) do |year|
start_month = (earliest_log_year.to_i == year) ? earliest_log_month.to_i : 1;
start_month.upto(12) do |month|
unless (year == Date.today.year and month >= Date.today.month)
month = "0" + month.to_s if month < 10
datestr = year.to_s + month.to_s + '??'
File.delete(opt[:temp_file]) if File.exists?(opt[:temp_file])
`cat logs/access_log.
`cat domains/*/logs/access_log.
`zcat logs/access_log.
`zcat domains/*/logs/access_log.
month_usage = `cat
@stats << [year.to_s + month.to_s, month_usage]
end
end
end
end
end
File.open(opt[:stat_file], 'w') {|f|
f.puts "# rsrcmeter historical statistics file"
f.puts "# Contains only completed months"
@stats.each {|i| f.puts i[0] + ',' + i[1].to_s}
}
datestr = Date.today.year.to_s + Date.today.month.to_s + "??"
`cat logs/access_log 2>/dev/null >
`cat domains/*/logs/access_log 2>/dev/null >>
`cat logs/access_log.
`cat domains/*/logs/access_log.
`zcat logs/access_log.
`zcat domains/*/logs/access_log.
usage = `cat
File.delete(opt[:temp_file]) if File.exists?(opt[:temp_file])
quotaline = `quota -g | tail -n 1`
disk_usage = `echo -n "#{quotaline}" | awk '{print $2}'`.to_f
disk_quota = `echo -n "#{quotaline}" | awk '{print $3}'`.to_f
disk_percent_used = (disk_usage / disk_quota) * 100
results = ""
results << "Disk usage: " + sprintf("%.4f", disk_usage / 1024) + " MiB (Quota: " + sprintf("%.4f", disk_quota / 1024 / 1024) +" GiB | " + sprintf("%.1f", disk_percent_used) + "% used)\n"
results << "Bandwidth:\n" + Date::ABBR_MONTHNAMES[Date.today.month] + " " + Date.today.year.to_s + ": " + sprintf("%.4f", usage) + " MiB (Month to Date)\n"
hist_usage = @stats.last(opt[:bw_months]).reverse
hist_usage.each {|h| results << Date::ABBR_MONTHNAMES[Date.parse(h[0] + "01").month] + ' ' + h[0][0,4] + ": " + sprintf("%.4f", (h[1].to_f / 1024 / 1024)) + " MiB\n"}
if opt[:email_to]
t = Time.now.strftime("%a %d %B %Y %H:%M:%S %Z")
message = <<EOM
From: TxD Resource Meter <#{ENV['USER']}-noreply@#{`/bin/hostname`.chomp}>
To: #{opt[:email_to]}
Subject: [TxD Resource Meter] #{t} report for #{ENV['USER']}
X-Mailer: rsrcmeter | http://textsnippets.com/posts/show/842
Resource Report - #{t}
#{results}
---------------
Generated by rsrcmeter
EOM
File.open("temp-emailresult", "w") { |file| file.print message }
`cat temp-emailresult | /usr/sbin/sendmail -t`
File.delete("temp-emailresult")
else
puts results
end