#!/usr/bin/env ruby require 'ostruct' class LinuxProcess < OpenStruct def initialize(args) super read_status! end def read_status! status = read_proc_file("status").scan(/(.*):[\t ]+(.*)/) self.name = status.find { |i| i.first == 'Name' }.last self.ppid = status.find { |i| i.first == 'PPid' }.last.to_i self.vm_size = status.find { |i| i.first == 'VmSize' }.last.split(' ').first.to_i rescue nil self.vm_rss = status.find { |i| i.first == 'VmRSS' }.last.split(' ').first.to_i rescue nil self.cmdline = self.read_proc_file("cmdline") end def read_smaps! smaps = read_proc_file("smaps").scan(/(.*):[\t ]+(.*)/) private_dirty = smaps.find_all { |i| i.first == 'Private_Dirty' } self.private_dirty = private_dirty.inject(0) { |i, pd| i + pd.last.split(' ').first.to_i } shared_dirty = smaps.find_all { |i| i.first == 'Shared_Dirty' } self.shared_dirty = shared_dirty.inject(0) { |i, sc| i + sc.last.split(' ').first.to_i } end def pid @pid ||= procfile.split('/').last.to_i end def read_proc_file(name) begin File.read(File.join("/proc/#{pid}", name)) rescue Errno::EACCES "" end end def self.all Dir.glob("/proc/[0-9]*").collect do |procfile| LinuxProcess.new :procfile => procfile end end end if !ARGV.empty? and ARGV.first =~ /[^0-9]+/ pid_name_selector = Regexp.new(ARGV.first) pid_selection = [] else pid_selection = ARGV.collect { |i| i.to_i } end LinuxProcess.all.each do |p| if pid_name_selector and pid_name_selector.match(p.cmdline) next if p.pid == Process.pid pid_selection << p.pid elsif (pid_selection & [p.pid, p.ppid]).empty? next else pid_selection << p.pid end p.read_smaps! puts "#{p.pid}: #{p.name} #{p.cmdline}" puts " vm_size:#{p.vm_size} kB vm_rss:#{p.vm_rss} kB private_dirty: #{p.private_dirty} kB shared_dirty: #{p.shared_dirty} kB" end