2 # -*- encoding: binary -*-
3 $stdout.sync = $stderr.sync = true
4 # this is used to show or watch the number of active and queued
5 # connections on any listener socket from the command line
11 usage = "Usage: #$0 [-d DELAY] [-t QUEUED_THRESHOLD] ADDR..."
12 ARGV.size > 0 or abort usage
16 # "normal" exits when driven on the command-line
17 trap(:INT) { exit 130 }
18 trap(:PIPE) { exit 0 }
20 opts = OptionParser.new('', 24, ' ') do |opts|
22 opts.on('-d', '--delay=DELAY', Float) { |n| delay = n }
23 opts.on('-t', '--queued-threshold=INT', Integer) { |n| queued_thresh = n }
28 addr =~ %r{\A(127\..+):(\d+)\z} or next
30 hex_port = '%X' % port.to_i
31 ip_addr = IPAddr.new(host)
32 hex_host = ip_addr.hton.each_byte.inject('') { |s,o| s << '%02X' % o }
33 socks = File.readlines('/proc/net/tcp')
34 hex_addr = "#{hex_host}:#{hex_port}"
35 if socks.grep(/^\s+\d+:\s+#{hex_addr}\s+/).empty? &&
36 ! socks.grep(/^\s+\d+:\s+00000000:#{hex_port}\s+/).empty?
37 warn "W: #{host}:#{port} (#{hex_addr}) not found in /proc/net/tcp"
38 warn "W: Did you mean 0.0.0.0:#{port}?"
46 bs = addr.respond_to?(:bytesize) ? addr.bytesize : addr.size
48 (addr =~ %r{\A/} ? unix : tcp) << addr
51 tcp = nil if tcp.empty?
52 unix = nil if unix.empty?
55 fmt = "%20s % #{len}s % 10u % 10u\n"
56 $stderr.printf fmt.tr('u','s'), *%w(timestamp address active queued)
63 tcp and combined.merge! Raindrops::Linux.tcp_listener_stats(tcp)
64 unix and combined.merge! Raindrops::Linux.unix_listener_stats(unix)
65 combined.each do |addr,stats|
66 next if stats.queued < queued_thresh
67 printf fmt, now ||= Time.now.utc.iso8601, addr, stats.active, stats.queued
69 end while delay && sleep(delay)