§ Monitoring your LAN

This is mostly a fun project, but you can generate nice charts with it, so I am happy to share it. It actually has a practical use case, if you stretch the ‘practical’ definition a bit. In any case if you ever wandered at what time and on which day a particular computer on your LAN is most probable to be online - this thing will answer that for you (after it gathers enough data and you do the math, that is).

§ The scripts

First goes the monitor script. It should run in the background on your main router if you want to catch all computers on your LAN. Also check the line which skips the IP of the router itself and the embedded filenames - you’ll most likely want to change them.

The monitor will fork into background, leave a pid file and a log file - I run it from cron at @reboot. If you want to dump the current state just send it a SIGUSR1.


if File.exists? 'arplog.dat'
  index_host, index_day = File.open('arplog.dat', 'r+') {|f| Marshal.load(f) }
  index_host = Hash.new
  index_day = Hash.new

pid = Process.fork do
  Signal.trap('USR1') do
    File.open('arplog.dat', 'w') {|f| f << Marshal.dump([index_host, index_day]) }
  Signal.trap('TERM') do
    File.open('arplog.dat', 'w') {|f| f << Marshal.dump([index_host, index_day]) }

  while true
    `arp -a`.scan(/.* \((.*?)\) at/) do |m|
      ip = m.first
      next if ip == ''

      stamp = Time.now
      time = stamp.strftime('%H%M')
      day = stamp.strftime('%A')

      index_host[ip] ||= Hash.new
      index_host[ip][day] ||= Hash.new
      index_host[ip][day][time] ||= 0
      index_host[ip][day][time] += 1

      index_day[day] ||= Hash.new
      index_day[day][time] ||= Hash.new
      index_day[day][time][ip] ||= 0
      index_day[day][time][ip] += 1


STDERR.puts("Detaching logger (PID #{pid}).")
File.open('arplogger.pid', 'w') {|f| f.puts pid }

And here goes a very minimal script which will give you the data in Excel format.


%w{date writeexcel}.each {|g| require g }

unless File.exists? 'arplog.dat'
  STDRR.puts 'No arplog.dat found, aborting.'

index_host, index_day = File.open('arplog.dat', 'r+') {|f| Marshal.load(f) }

book = WriteExcel.new('report.xls')
bold = book.add_format(:bold => 1)

index_host.each_pair do |ip, data|
  # prepare worksheet
  sheet = book.add_worksheet(ip)
  sheet.write('A2', [0.upto(23).collect {|h| 0.upto(59).collect \
              {|m| '%0.2d%0.2d' % [h, m]}}.flatten], bold)
  sheet.write('B1', DateTime::DAYNAMES, bold)

  # fill in data
  column = 1
  DateTime::DAYNAMES.each do |day|
    row = 1
    0.upto(23).each do |h|
      0.upto(59).each do |m|
        if data.has_key? day
          number = data[day]['%0.2d%0.2d' % [h, m]] || 0
          number = 0
        sheet.write_number(row, column, number)
        row += 1
    column += 1


§ The results

Here are some charts, done in Gnumeric after a couple of weeks of running the monitor.

First graph.

Second graph.

comments powered by Disqus
Last update: 2012-12-22. » LINK » TXT » ATOM. Go to the top. Licence CC-BY-NC-SA.
If you find this interesting go ahead and leave a comment or add a star.
Any and all feedback is appreciated!