Skip to topic | Skip to bottom
Note: Included topic Gulli.WebTopBar? does not exist yet
Gulli
Gulli.LogSnarferr1.1 - 02 Jun 2005 - 21:11 - TWikiGuesttopic end

Start of topic | Skip to actions

a ruby script for scanning the system befindlichkeit of a linux system

a small ruby script to scans logfiles, /proc/stat and /proc/net/dev for data and spits out osc messages for these:


# scans /proc/stat and /proc/net/dev
# spits aout osc messages if there are RELATIVE CHNAGES ONLY
# since most/all of the data in these files is counters
# we keep a back reference to the data scanned in the loop before,
# calculate differences and if these are > 0 the fire the messages

# (c) 2003 andi@mego.at
# part of the gull
# code covered by the GPL

require 'oscsend'

# this is the sleep value between consecutive loops
SCANDELAY = 0.05

# the tail command used to tail
# this reqires special privileges on proper systems.
TAILCOMMAND = 'sudo tail -f -s 0.01 /var/log/syslog /var/log/mail.log'


if ARGV.length != 2
   print "usage: stat.rb send-to-host portno\n"
   exit
end

sendhost = ARGV[0].to_s
sendport = ARGV[1].to_i

hostname = `hostname -f`
hostname.chop!

print "sending from #{hostname} to #{sendhost} #{sendport}\n"


# the actions hash holds actions for the different stat data types.
actions = Hash.new(proc {})

# keep a reference to the previous raw data
prevdata = Hash.new

# keep a reference to the previous sent data (difference values)
# is used to decide if we send data
prevsent = Hash.new
# fill the actions array. used only for stat data, net data is handled
# differently
actions["cpu"] = proc {
                 |data|
                 x = prevdata["cpu"]
                 send = Array.new
                 data.length.times {
                   |i|
                   send[i] = data[i] - x[i]
                 }
                 send
         }

# only scan the first 16 interrupts
actions["intr"] = proc {
                 |data|
                 x = prevdata["intr"]
                 send = Array.new
                 16.times {
                   |i|
                   send[i] = data[i] - x[i]
                 }
                 send
         }

actions["processes"] = proc {
                 |data|
                 x = prevdata["processes"]
                 send = Array.new
                 data.length.times {
                   |i|
                   send[i] = data[i] - x[i]
                 }
                 send
         }

actions["page"] = proc {
                 |data|
                 x = prevdata["page"]
                 send = Array.new
                 data.length.times {
                   |i|
                   send[i] = data[i] - x[i]
                 }
                 send
         }

actions["swap"] = proc {
                 |data|
                 x = prevdata["swap"]
                 send = Array.new
                 data.length.times {
                   |i|
                   send[i] = data[i] - x[i]
                 }
                 send
         }


# for logfile-tailer
def process_data(data)
  case data
  when /-- MARK --/
    return ["MARK"]
  when /^last/
    return ["repeat"]
  when /kernel:/
    info = /kernel: (.*)/.match(data)[1].to_s()
    return ["kernel", /^kernel: (.*)/.match(data)[1].to_s()]
  else
    info = /^([^ [:]*)/.match(data)[1].to_s()
    return [info]
  end
end



###################
#### main loop

# create logfile tailer thread (lightweigth ruby thread..)

tthread = Thread.new(sendhost, sendport) {
                     | sendhost, sendport |
                     lprevtime = Hash.new

                     r = Regexp.new("^([^ ]* *[^ ]* *[^ ]*) *([^ ]*) *(.*)")
                     f = IO.popen(TAILCOMMAND).each() {
                       |l|
                       if l != "\n" && !(/^==/.match(l)) # wipe "==> bla <==" from tailing more logfiles
                         m = r.match(l)
                         time = m[1]
                         host = m[2]
                         data = process_data(m[3])
                         #    $stdout << host << " " << time << "\n" << data[0] << "\n"
                         if lprevtime[data[0]] == nil
                           lprevtime[data[0]] = Time.new
                         end
                         timediff = Time.new.to_f - lprevtime[data[0]].to_f
                         Osc::OscMessage.new("/sysmon/#{hostname}/log", data + [timediff,time]).send_to("192.168.1.52", 5151)
                       end
                     }
                     f.close()

}

while 1
  # check /proc/stat
  lines = IO.readlines("/proc/stat")
  lines.each {
    | line |
    items = line.split
    what = items[0]
    data = items[1..items.length]
    # convert data to integer types
    data.collect! {|x| x.to_i}
    # fill an initial prevdata
    if prevdata[what] == nil
       prevdata[what] = data.dup
    end
    # call the matching method in actions hash
    s = actions[what].call(data)
    # check if its time to send
    if prevsent[what] != s
      Osc::OscMessage.new("/sysmon/"+hostname+"/proc", [what] + s).send_to(sendhost, sendport)
      prevsent[what] = s.dup
    end
    # store previous data for the next loop
    prevdata[what] = data.dup
  }
  # check /proc/net/dev
  lines = IO.readlines("/proc/net/dev")
  # weed first two lines (headers)
  lines = lines[2..lines.length]
  lines.each {
    | line |
    # substitute the colon after the interface name
    line.sub!(/:/, ' ')

    items = line.split
    what = items[0]
    data = items[1..items.length]
     data.collect! {|x| x.to_i}
     if prevdata[what] == nil
       prevdata[what] = data.dup
     end
     x = prevdata[what]
     s = Array.new
     data.length.times {
        |i|
        s[i] = data[i] - x[i]
     }
     # this does not happen usually, could be left out. theres always
     # activity ion the net..
     if prevsent[what] != s
       Osc::OscMessage.new("/sysmon/"+hostname+"/net", [what]+s).send_to(sendhost, sendport)
       prevsent[what] = s.dup
     end
     prevdata[what] = data.dup
  }
  # zzzzz for scandelay seconds
  sleep(SCANDELAY)
end


-- Main.andi - 02 Jun 2003
to top


You are here: Gulli > ActivityLog > ProtoGuller > LogSnarfer

to top

Copyright © 1999-2018 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback