| 1 | #! /bin/ruby -Ku |
|---|
| 2 | |
|---|
| 3 | require 'backtick' |
|---|
| 4 | require 'thread' |
|---|
| 5 | require 'open-uri' |
|---|
| 6 | require 'json' |
|---|
| 7 | require 'time' |
|---|
| 8 | require 'cgi' |
|---|
| 9 | |
|---|
| 10 | STDOUT.sync = true |
|---|
| 11 | Cons = Struct.new :car, :cdr |
|---|
| 12 | A = [Cons.new] |
|---|
| 13 | M = Mutex.new |
|---|
| 14 | A.last.cdr = A.first |
|---|
| 15 | |
|---|
| 16 | def showline i, j, k |
|---|
| 17 | t = j.strftime '%H:%M:%S' |
|---|
| 18 | x = attribute ' dB', i |
|---|
| 19 | d = /.{0,140}/.match k.chomp |
|---|
| 20 | printf "[%s %s] %s\n", t, x, d[0] |
|---|
| 21 | end |
|---|
| 22 | |
|---|
| 23 | def push who, what |
|---|
| 24 | what.each do |(t, i)| |
|---|
| 25 | showline who, t, i |
|---|
| 26 | end |
|---|
| 27 | c = Cons.new [who, what], nil |
|---|
| 28 | A.last.cdr = c |
|---|
| 29 | A.shift if A.size >= 8 |
|---|
| 30 | A.push c |
|---|
| 31 | c.cdr = A.first |
|---|
| 32 | end |
|---|
| 33 | |
|---|
| 34 | def plugin |
|---|
| 35 | Thread.start do |
|---|
| 36 | loop do |
|---|
| 37 | begin |
|---|
| 38 | yield |
|---|
| 39 | rescue Exception => e |
|---|
| 40 | b = e.backtrace.map {|i| [Time.now, i] } |
|---|
| 41 | b.reverse! |
|---|
| 42 | M.synchronize do |
|---|
| 43 | push 'exception', [[Time.now, attribute('bB RI', e.message)]] |
|---|
| 44 | push 'trace', b |
|---|
| 45 | end |
|---|
| 46 | end |
|---|
| 47 | sleep 30 |
|---|
| 48 | end |
|---|
| 49 | end |
|---|
| 50 | end |
|---|
| 51 | |
|---|
| 52 | def selective cmd |
|---|
| 53 | r1 = /^/ |
|---|
| 54 | r2 = /[\r\n]/ |
|---|
| 55 | open "| sudo #{cmd}", 'rb' do |f| |
|---|
| 56 | s = '' |
|---|
| 57 | t = '' |
|---|
| 58 | loop do |
|---|
| 59 | # sleep 2 |
|---|
| 60 | IO.select [f] |
|---|
| 61 | f.read_nonblock 4096, s |
|---|
| 62 | t << s |
|---|
| 63 | a = t.split r1 |
|---|
| 64 | t = r2.match(a.last) ? '' : a.pop |
|---|
| 65 | M.synchronize do |
|---|
| 66 | yield a |
|---|
| 67 | end |
|---|
| 68 | end |
|---|
| 69 | end |
|---|
| 70 | end |
|---|
| 71 | |
|---|
| 72 | # syslog thread |
|---|
| 73 | plugin do |
|---|
| 74 | r = %r' |
|---|
| 75 | \A( |
|---|
| 76 | (?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s |
|---|
| 77 | [\s123]\d\s\d\d:\d\d:\d\d |
|---|
| 78 | )\s |
|---|
| 79 | .+?:\s(.*) |
|---|
| 80 | \z |
|---|
| 81 | 'xmn |
|---|
| 82 | selective 'tail -f -n 300 /var/log/syslog' do |a| |
|---|
| 83 | a.map! {|i| r.match i } |
|---|
| 84 | a.compact! |
|---|
| 85 | a.map! {|i| [Time.parse(i[1]), i[2]] } |
|---|
| 86 | push 'syslog', a |
|---|
| 87 | end |
|---|
| 88 | end |
|---|
| 89 | |
|---|
| 90 | # tshark thread |
|---|
| 91 | plugin do |
|---|
| 92 | r = /^\s+(?:[\d\.]+)\s(.+)$/ |
|---|
| 93 | selective "tshark -i any 'tcp and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'" do |a| |
|---|
| 94 | t = Time.now |
|---|
| 95 | a.map! {|i| r.match i } |
|---|
| 96 | a.compact! |
|---|
| 97 | a.map! {|i| i[1] } |
|---|
| 98 | a.each do |i| |
|---|
| 99 | showline 'tshark', t, i |
|---|
| 100 | end |
|---|
| 101 | end |
|---|
| 102 | end |
|---|
| 103 | |
|---|
| 104 | # twitter thread |
|---|
| 105 | plugin do |
|---|
| 106 | # should be at most 170 [req./hour] |
|---|
| 107 | opts = { :http_basic_authentication => %w'username password' } |
|---|
| 108 | uri = 'http://api.twitter.com/1/statuses/home_timeline.json' |
|---|
| 109 | since = '' |
|---|
| 110 | loop do |
|---|
| 111 | j = open "#{uri}#{since}", 'rb', opts do |f| |
|---|
| 112 | JSON.parse(f.read).sort_by {|i| i['id'] } |
|---|
| 113 | end |
|---|
| 114 | unless j.empty? |
|---|
| 115 | M.synchronize do |
|---|
| 116 | j.each do |i| |
|---|
| 117 | t = Time.parse i['created_at'] |
|---|
| 118 | s = CGI.unescapeHTML i['text'] |
|---|
| 119 | w = attribute 'b dG', i['user']['screen_name'] |
|---|
| 120 | push 'twitter', [[t, "@#{w}> #{s}"]] |
|---|
| 121 | end |
|---|
| 122 | since = "?since_id=#{j.last['id']}" |
|---|
| 123 | end |
|---|
| 124 | end |
|---|
| 125 | sleep 127 |
|---|
| 126 | end |
|---|
| 127 | end |
|---|
| 128 | |
|---|
| 129 | i = A.first |
|---|
| 130 | loop do |
|---|
| 131 | sleep 2 |
|---|
| 132 | M.synchronize do |
|---|
| 133 | j, i = i.car, i.cdr |
|---|
| 134 | next unless j |
|---|
| 135 | who, what = *j |
|---|
| 136 | what.each do |(t, k)| |
|---|
| 137 | showline who, t, k |
|---|
| 138 | sleep 0.07 |
|---|
| 139 | end |
|---|
| 140 | end |
|---|
| 141 | end |
|---|
| 142 | |
|---|
| 143 | # Local Variables: |
|---|
| 144 | # mode: ruby |
|---|
| 145 | # coding: utf-8 |
|---|
| 146 | # indent-tabs-mode: t |
|---|
| 147 | # tab-width: 3 |
|---|
| 148 | # ruby-indent-level: 3 |
|---|
| 149 | # fill-column: 79 |
|---|
| 150 | # default-justification: full |
|---|
| 151 | # End: |
|---|
| 152 | # vi: ts=3 sw=3 |
|---|