module Eye::System

Public Class Methods

check_pid_alive(pid) click to toggle source

Check that pid really exits very fast return result hash

# File lib/eye/system.rb, line 11
def check_pid_alive(pid)
  res = if pid
    ::Process.kill(0, pid)
  else
    false
  end

  {:result => res}
rescue => ex
  {:error => ex}
end
daemonize(cmd, cfg = {}) click to toggle source

Daemonize cmd, and detach options:

:pid_file
:working_dir
:environment
:stdin, :stdout, :stderr
# File lib/eye/system.rb, line 58
def daemonize(cmd, cfg = {})
  pid = ::Process::spawn(prepare_env(cfg), *Shellwords.shellwords(cmd), spawn_options(cfg))

  {:pid => pid, :exitstatus => 0}

rescue Errno::ENOENT, Errno::EACCES => ex
  {:error => ex}

ensure
  Process.detach(pid) if pid
end
execute(cmd, cfg = {}) click to toggle source

Execute cmd with blocking, return status (be careful: inside actor blocks it mailbox, use with defer) options

:working_dir
:environment
:stdin, :stdout, :stderr
# File lib/eye/system.rb, line 75
def execute(cmd, cfg = {})
  pid = ::Process::spawn(prepare_env(cfg), *Shellwords.shellwords(cmd), spawn_options(cfg))

  timeout = cfg[:timeout] || 1.second
  status = 0

  Timeout.timeout(timeout) do
    _, st = Process.waitpid2(pid)
    status = st.exitstatus || st.termsig
  end

  {:pid => pid, :exitstatus => status}

rescue Timeout::Error => ex
  if pid
    warn "[#{cfg[:name]}] sending :KILL signal to <#{pid}> due to timeout (#{timeout}s)"
    send_signal(pid, 9)
  end
  {:error => ex}

rescue Errno::ENOENT, Errno::EACCES => ex
  {:error => ex}

ensure
  Process.detach(pid) if pid
end
normalized_file(file, working_dir = nil) click to toggle source

normalize file

# File lib/eye/system.rb, line 103
def normalized_file(file, working_dir = nil)
  Pathname.new(file).expand_path(working_dir).to_s
end
pid_alive?(pid) click to toggle source

Check that pid really exits very fast return true/false

# File lib/eye/system.rb, line 26
def pid_alive?(pid)
  res = check_pid_alive(pid)
  !!res[:result]
end
prepare_env(config = {}) click to toggle source
# File lib/eye/system.rb, line 128
def prepare_env(config = {})
  env = {}

  (config[:environment] || {}).each do |k,v|
    env[k.to_s] = v && v.to_s
  end

  env
end
send_signal(pid, code = :TERM) click to toggle source

Send signal to process (uses for kill) code: TERM(15), KILL(9), QUIT(3), …

# File lib/eye/system.rb, line 33
def send_signal(pid, code = :TERM)
  code = 0 if code == '0'
  if code.to_s.to_i != 0
    code = code.to_i
    code = -code if code < 0
  end
  code = code.to_s.upcase if code.is_a?(String) || code.is_a?(Symbol)

  if pid
    ::Process.kill(code, pid)
    {:result => :ok}
  else
    {:error => Exception.new('no_pid')}
  end

rescue => ex
  {:error => ex}
end
spawn_options(config = {}) click to toggle source
# File lib/eye/system.rb, line 107
def spawn_options(config = {})
  options = {
    pgroup: true,
    chdir: config[:working_dir] || '/'
  }

  options[:out]   = [config[:stdout], 'a'] if config[:stdout]
  options[:err]   = [config[:stderr], 'a'] if config[:stderr]
  options[:in]    = config[:stdin] if config[:stdin]
  options[:umask] = config[:umask] if config[:umask]
  options[:close_others] = false if config[:preserve_fds]
  options[:unsetenv_others] = true if config[:clear_env]

  if Eye::Local.root?
    options[:uid] = Etc.getpwnam(config[:uid]).uid if config[:uid]
    options[:gid] = Etc.getgrnam(config[:gid]).gid if config[:gid]
  end

  options
end