class Epi::RunningProcess

noinspection RubyTooManyInstanceVariablesInspection

Constants

DEFAULT_TIMEOUT
PS_FORMAT

Attributes

pid[R]

Public Class Methods

group_name(gid) click to toggle source
# File lib/epi/running_process.rb, line 17
def group_name(gid)
  groups[gid.to_i]
end
new(pid, ps_line: nil, job: nil) click to toggle source
# File lib/epi/running_process.rb, line 50
def initialize(pid, ps_line: nil, job: nil)
  @pid = pid.to_i
  @ps_line = ps_line
  @props = {}
  @job = job
  reload! unless ps_line
end
user_name(uid) click to toggle source
# File lib/epi/running_process.rb, line 13
def user_name(uid)
  @users[uid.to_i] ||= %x[#{username_lookup_cmd % uid}].chomp
end

Private Class Methods

groups() click to toggle source
# File lib/epi/running_process.rb, line 23
def groups
  @groups ||= read_groups
end
read_groups() click to toggle source
# File lib/epi/running_process.rb, line 32
def read_groups
  {}.tap do |result|
    File.readlines('/etc/group').each do |line|
      result[$2.to_i] = $1 if line =~ /^([^:]+):[^:]+:(-?\d+):/
    end
  end
end
username_lookup_cmd() click to toggle source
# File lib/epi/running_process.rb, line 27
def username_lookup_cmd
  # Use `id -un` on Mac OS, and `getent passwd` on Linux
  @username_lookup_cmd ||= `uname`.chomp == 'Darwin' ? 'id -un %s' : 'getent passwd %s | cut -d: -f1'
end

Public Instance Methods

command() click to toggle source

The command that was used to start the process, including its arguments @return [String]

# File lib/epi/running_process.rb, line 125
def command
  @command ||= parts[12]
end
cpu_percentage() click to toggle source

CPU usage as a percentage @return [Float]

# File lib/epi/running_process.rb, line 71
def cpu_percentage
  @cpu_percentage ||= parts[1].to_f
end
group() click to toggle source

Name of the group that owns the process @return [String]

# File lib/epi/running_process.rb, line 119
def group
  @group ||= self.class.group_name parts[11]
end
job() click to toggle source
# File lib/epi/running_process.rb, line 164
def job
  @job ||= Jobs.by_pid[pid]
end
kill(timeout = DEFAULT_TIMEOUT) click to toggle source

Kill a running process @param timeout [TrueClass|FalseClass|Numeric] ‘true` to kill immediately (KILL),

`false` to kill gracefully (TERM), or a number of seconds to wait between trying
both (first TERM, then KILL).

@return [RunningProcess]

# File lib/epi/running_process.rb, line 140
def kill(timeout = DEFAULT_TIMEOUT)
  if timeout.is_a? Numeric
    begin
      logger.info "Will wait #{timeout} second#{timeout != 1 && 's'} for process to terminate gracefully"
      Timeout::timeout(timeout) { kill false }
    rescue Timeout::Error
      kill true
    end
  else
    signal = timeout ? 'KILL' : 'TERM'
    logger.info "Sending #{signal} to process #{pid}"
    Process.kill signal, pid rescue Errno::ESRCH false
    sleep 0.2 while `ps -p #{pid} > /dev/null 2>&1; echo $?`.chomp.to_i == 0
    logger.info "Process #{pid} terminated by signal #{signal}"
  end
  self
end
kill!() click to toggle source

Kill a running process immediately and synchronously with kill -9 @return [RunningProcess]

# File lib/epi/running_process.rb, line 160
def kill!
  kill true
end
logger() click to toggle source
# File lib/epi/running_process.rb, line 46
def logger
  Epi.logger
end
memory_percentage() click to toggle source

Physical memory usage as a percentage @return [Float]

# File lib/epi/running_process.rb, line 77
def memory_percentage
  @memory_percentage ||= parts[2].to_f
end
physical_memory() click to toggle source

Physical memory usage in bytes (rounded to the nearest kilobyte) @return [Fixnum]

# File lib/epi/running_process.rb, line 83
def physical_memory
  @physical_memory ||= parts[3].to_i * 1024
end
reload!() click to toggle source
# File lib/epi/running_process.rb, line 58
def reload!
  @props = {}
  @parts = nil
  @ps_line = `ps -p #{pid} -o #{PS_FORMAT}`.lines[1]
end
restart!() click to toggle source
# File lib/epi/running_process.rb, line 168
def restart!
  raise Exceptions::Fatal, 'Cannot restart this process because it is not managed by a job' unless job
  job.replace pid
end
root?() click to toggle source

Whether the process is root-owned @return [TrueClass|FalseClass]

# File lib/epi/running_process.rb, line 131
def root?
  user == 'root'
end
started_at() click to toggle source

Time at which the process was started @return [Time]

# File lib/epi/running_process.rb, line 101
def started_at
  @started_at ||= Time.parse parts[5..9].join ' '
end
total_memory() click to toggle source

Sum of {#physical_memory} and {#total_memory} @return [Fixnum]

# File lib/epi/running_process.rb, line 95
def total_memory
  @total_memory ||= physical_memory + virtual_memory
end
uptime() click to toggle source

Duration the process has been running (in seconds) @return [Float]

# File lib/epi/running_process.rb, line 107
def uptime
  Time.now - started_at
end
user() click to toggle source

Name of the user that owns the process @return [String]

# File lib/epi/running_process.rb, line 113
def user
  @user ||= self.class.user_name parts[10]
end
virtual_memory() click to toggle source

Virtual memory usage in bytes (rounded to the nearest kilobyte) @return [Fixnum]

# File lib/epi/running_process.rb, line 89
def virtual_memory
  @virtual_memory ||= parts[4].to_i * 1024
end
was_alive?() click to toggle source

Returns ‘true` if the process was running when this instance was created

# File lib/epi/running_process.rb, line 65
def was_alive?
  !@ps_line.nil?
end

Private Instance Methods

parts() click to toggle source
# File lib/epi/running_process.rb, line 175
def parts
  raise 'Tried to access details of a non-running process' unless String === @ps_line
  @parts ||= @ps_line.strip.split(/\s+/, 13)
end