‰PNG  IHDR @ @ ªiqÞ pHYs   šœ —tEXtComment #!/usr/bin/env ruby # Parses a file descriptor log as produced by Passenger, # and display the file descriptors that are still open # according to the log. class ParserApp Agent = Struct.new(:name, :fds) Entry = Struct.new(:source, :purpose) def initialize(path) @io = File.open(path, "r") @agents = {} end def close @io.close end def analyze @lineno = 1 while !@io.eof? line = @io.readline.strip pid, source, message = parse_line(line) case message when /^Starting agent: (.+)$/ agent_name = $1 if (old_pid = find_agent(agent_name)) warn "#{agent_name} restarted" @agents.delete(old_pid) end @agents[pid] = Agent.new(agent_name, {}) when /^File descriptor opened: (.+)/ fd = $1.to_i if agent = @agents[pid] if agent.fds.has_key?(fd) warn "FD #{fd} already opened" end agent.fds[fd] = Entry.new(source) else warn "No agent information about #{pid}" end when /^File descriptor closed: (.+)/ fd = $1.to_i if agent = @agents[pid] if agent.fds.has_key?(fd) agent.fds.delete(fd) else warn "FD #{fd} not opened" end else warn "No agent information about #{pid}" end when /^File descriptor purpose: (.+?): (.+)/ fd = $1.to_i purpose = $2 if agent = @agents[pid] if entry = agent.fds[fd] entry.purpose = purpose else warn "FD #{fd} not opened" end else warn "No agent information about #{pid}" end end @lineno += 1 end rescue EOFError end def report @agents.each_pair do |pid, agent| puts puts "#{pid}: #{agent.name}" puts("-" * 80) agent.fds.keys.sort.each do |fd| entry = agent.fds[fd] printf "%-5d %-30s %s\n", fd, entry.source, entry.purpose end end end private def parse_line(line) if line =~ /^\[ (.+?) \]: (.+)/ info = $1 message = $2 fragments = info.split(" ") pid = fragments[2].sub(/\/.*/, '') source = fragments.last [pid, source, message] else nil end end def find_agent(name) @agents.each_pair do |pid, agent| if agent.name == name return pid end end nil end def warn(message) STDERR.puts "Warning:#{@lineno}: #{message}" end end app = ParserApp.new(ARGV[0]) app.analyze app.report app.close