module Kanrisuru::Core::System
Constants
- CPUArchitecture
- CPUArchitectureVulnerability
- KernelStatistic
- KernelStatisticCpu
- LoginUser
- OpenFile
- ProcessInfo
- SessionDetail
- Uptime
- UserLoggedIn
Public Instance Methods
cpu_info(spec)
click to toggle source
# File lib/kanrisuru/core/system.rb, line 237 def cpu_info(spec) Kanrisuru.logger.info do 'DEPRECATION WARNING: cpu_info will be removed in the upcoming major release. Use lscpu instead.' end name = case spec when 'sockets' '^Socket' when 'cores_per_socket' '^Core' when 'threads' '^Thread' when 'cores' '^CPU(' else return end command = Kanrisuru::Command.new("lscpu | grep -i '#{name}' | awk '{print $NF}'") execute(command) Kanrisuru::Result.new(command, &:to_i) end
free(type)
click to toggle source
# File lib/kanrisuru/core/system.rb, line 271 def free(type) conversions = { total: 'MemTotal', free: 'MemFree', swap: 'SwapTotal', swap_free: 'SwapFree' } option = conversions[type.to_sym] raise ArgumentError, 'Invalid mem type' unless option command = Kanrisuru::Command.new("cat /proc/meminfo | grep -i '^#{option}' | awk '{print $2}'") execute(command) ## In kB Kanrisuru::Result.new(command, &:to_i) end
kernel_statistics()
click to toggle source
# File lib/kanrisuru/core/system.rb, line 451 def kernel_statistics command = Kanrisuru::Command.new('cat /proc/stat') execute_shell(command) Kanrisuru::Result.new(command) do |cmd| lines = cmd.to_a result = KernelStatistic.new result.cpus = [] lines.each do |line| values = line.split field = values[0] values = values[1..-1].map(&:to_i) case field when /^cpu/ cpu_stat = KernelStatisticCpu.new cpu_stat.user = values[0] cpu_stat.nice = values[1] cpu_stat.system = values[2] cpu_stat.idle = values[3] cpu_stat.iowait = values[4] cpu_stat.irq = values[5] cpu_stat.softirq = values[6] cpu_stat.steal = values[7] cpu_stat.guest = values[8] cpu_stat.guest_nice = values[9] case field when /^cpu$/ result.cpu_total = cpu_stat when /^cpu\d+/ result.cpus << cpu_stat end when 'intr' result.interrupt_total = values[0] result.interrupts = values[1..-1] when 'softirq' result.softirq_total = values[0] result.softirqs = values[1..-1] else result[field] = values[0] end end result end end
kill(signal, pids)
click to toggle source
# File lib/kanrisuru/core/system.rb, line 382 def kill(signal, pids) raise ArgumentError, 'Invalid signal' unless Kanrisuru::Util::Signal.valid?(signal) ## Use named signals for readabilitiy signal = Kanrisuru::Util::Signal[signal] if signal.instance_of?(Integer) command = Kanrisuru::Command.new('kill') command << "-#{signal}" command << (pids.instance_of?(Array) ? pids.join(' ') : pids) execute_shell(command) Kanrisuru::Result.new(command) end
kstat()
click to toggle source
# File lib/kanrisuru/core/system.rb, line 447 def kstat kernel_statistics end
last(opts = {})
click to toggle source
# File lib/kanrisuru/core/system.rb, line 289 def last(opts = {}) command = if opts[:failed_attempts] Kanrisuru::Command.new('lastb') else Kanrisuru::Command.new('last') end command.append_flag('-i') command.append_flag('-F') command.append_arg('-f', opts[:file]) ## Some systems only use 1 space between user and TTY field ## Add an additional space in output formatting for simple parsing ## logic. command | "sed 's/ / /'" execute_shell(command) Kanrisuru::Result.new(command) do |cmd| lines = cmd.to_a mapping = {} lines.each do |line| next if Kanrisuru::Util.blank?(line) next if line.include?('wtmp') || line.include?('btmp') line = line.gsub(' still logged in', '- still logged in') if line.include?('still logged in') values = line.split(/\s{2,}/, 4) user = values[0] tty = values[1] ip = IPAddr.new(values[2]) date_range = values[3] login, logout = date_range.split(' - ') login = parse_last_date(login) if login logout = parse_last_date(logout) if logout detail = SessionDetail.new detail.tty = tty detail.ip_address = ip detail.login_at = login detail.logout_at = logout detail.success = !Kanrisuru::Util.present?(opts[:failed_attemps]) mapping[user] = LoginUser.new(user, []) unless mapping.key?(user) mapping[user].sessions << detail end mapping.values end end
load_average()
click to toggle source
# File lib/kanrisuru/core/system.rb, line 262 def load_average command = Kanrisuru::Command.new("cat /proc/loadavg | awk '{print $1,$2,$3}'") execute(command) Kanrisuru::Result.new(command) do |cmd| cmd.to_s.split.map(&:to_f) end end
load_env()
click to toggle source
# File lib/kanrisuru/core/system.rb, line 134 def load_env command = Kanrisuru::Command.new('env') execute_shell(command) Kanrisuru::Result.new(command) do |cmd| string = cmd.to_s hash = {} rows = string.split("\n") rows.each do |row| key, value = row.split('=', 2) hash[key] = value end hash end end
lscpu()
click to toggle source
# File lib/kanrisuru/core/system.rb, line 152 def lscpu command = Kanrisuru::Command.new('lscpu') execute_shell(command) Kanrisuru::Result.new(command) do |cmd| lines = cmd.to_a result = CPUArchitecture.new result.vulnerabilities = [] result.numa_nodes = [] lines.each do |line| values = line.split(': ', 2) field = values[0].strip data = values[1].strip case field when 'Architecture' result.architecture = data when 'CPU op-mode(s)' result.operation_modes = data.split(', ') when 'Byte Order' result.byte_order = data when 'Address sizes' result.address_sizes = data.split(', ') when 'CPU(s)' result.cores = data.to_i when 'On-line CPU(s) list' result.online_cpus = data.to_i when 'Thread(s) per core' result.threads_per_core = data.to_i when 'Core(s) per socket' result.cores_per_socket = data.to_i when 'Socket(s)' result.sockets = data.to_i when 'NUMA node(s)' result.numa_nodes = data.to_i when 'Vendor ID' result.vendor_id = data when 'CPU family' result.cpu_family = data.to_i when 'Model' result.model = data.to_i when 'Model name' result.model_name = data when 'Stepping' result.stepping = data.to_i when 'CPU MHz' result.cpu_mhz = data.to_f when 'CPU max MHz' result.cpu_max_mhz = data.to_f when 'CPU min MHz' result.cpu_min_mhz = data.to_f when 'CPUBogoMIPS' result.bogo_mips = data.to_f when 'Virtualization' result.virtualization = data when 'Hypervisor vendor' result.hypervisor_vendor = data when 'Virtualization type' result.virtualization_type = data when 'L1d cache' result.l1d_cache = data when 'L1i cache' result.l1i_cache = data when 'L2 cache' result.l2_cache = data when 'L3 cache' result.l3_cache = data when /^Numa node/ result.numa_nodes << data.split(',') when /^Vulnerability/ name = field.split('Vulnerability ')[1] result.vulnerabilities << CPUArchitectureVulnerability.new(name, data) when 'Flags' result.flags = data.split end end result end end
lsof(_opts = {})
click to toggle source
# File lib/kanrisuru/core/system.rb, line 397 def lsof(_opts = {}) command = Kanrisuru::Command.new('lsof -F pcuftDsin') execute_shell(command) Kanrisuru::Result.new(command) do |cmd| lines = cmd.to_a current_row = nil current_pid = nil current_user = nil current_command = nil rows = [] lines.each do |line| case line when /^p/ current_pid = parse_lsof(line, 'p').to_i when /^c/ current_command = parse_lsof(line, 'c') when /^u/ current_user = parse_lsof(line, 'u').to_i when /^f/ rows << current_row if current_row current_row = OpenFile.new current_row.pid = current_pid current_row.command = current_command current_row.uid = current_user current_row.file_descriptor = parse_lsof(line, 'f') when /^t/ current_row.type = parse_lsof(line, 't') when /^D/ current_row.device = parse_lsof(line, 'D') when /^s/ current_row.fsize = parse_lsof(line, 's').to_i when /^i/ current_row.inode = parse_lsof(line, 'i').to_i when /^n/ current_row.name = parse_lsof(line, 'n') end end rows << current_row if current_row rows end end
poweroff(opts = {})
click to toggle source
# File lib/kanrisuru/core/system.rb, line 603 def poweroff(opts = {}) time = opts[:time] cancel = opts[:cancel] message = opts[:message] no_wall = opts[:no_wall] command = Kanrisuru::Command.new('shutdown') if Kanrisuru::Util.present?(cancel) command.append_flag('-c') command << message if message else time = format_shutdown_time(time) if Kanrisuru::Util.present?(time) if Kanrisuru::Util.present?(no_wall) command.append_flag('--no-wall') else command << time if time command << message if message end end begin execute_shell(command) Kanrisuru::Result.new(command) rescue IOError ## When powering off 'now', ssh io stream closes ## Set exit status to 0 command.handle_status(0) Kanrisuru::Result.new(command) end end
ps(opts = {})
click to toggle source
# File lib/kanrisuru/core/system.rb, line 348 def ps(opts = {}) group = opts[:group] user = opts[:user] pid = opts[:pid] ppid = opts[:ppid] # tree = opts[:tree] command = Kanrisuru::Command.new('ps ww') if !user.nil? || !group.nil? || !pid.nil? || !ppid.nil? command.append_arg('--user', user.instance_of?(Array) ? user.join(',') : user) command.append_arg('--group', group.instance_of?(Array) ? group.join(',') : group) command.append_arg('--pid', pid.instance_of?(Array) ? pid.join(',') : pid) command.append_arg('--ppid', ppid.instance_of?(Array) ? ppid.join(',') : ppid) else command.append_flag('ax') end command.append_arg('-o', 'uid,user,gid,group,ppid,pid,pcpu,pmem,stat,pri,flags,policy,time,cmd') command.append_flag('--no-headers') execute(command) ## Have found issues with regular newline parsing from command ## most likely a buffer overflow from SSH buffer. ## Join string then split by newline. Kanrisuru::Result.new(command) do |cmd| result_string = cmd.raw_result.join rows = result_string.split("\n") build_process_list(rows) end end
reboot(opts = {})
click to toggle source
# File lib/kanrisuru/core/system.rb, line 568 def reboot(opts = {}) time = opts[:time] cancel = opts[:cancel] message = opts[:message] no_wall = opts[:no_wall] command = Kanrisuru::Command.new('shutdown') if Kanrisuru::Util.present?(cancel) command.append_flag('-c') command << message if message else command.append_flag('-r') time = format_shutdown_time(time) if Kanrisuru::Util.present?(time) if Kanrisuru::Util.present?(no_wall) command.append_flag('--no-wall') else command << time if time command << message if message end end begin execute_shell(command) Kanrisuru::Result.new(command) rescue IOError ## When rebooting 'now', ssh io stream closes ## Set exit status to 0 command.handle_status(0) Kanrisuru::Result.new(command) end end
uptime()
click to toggle source
# File lib/kanrisuru/core/system.rb, line 502 def uptime ## Ported from https://github.com/djberg96/sys-uptime command = Kanrisuru::Command.new('cat /proc/uptime') execute_shell(command) Kanrisuru::Result.new(command) do |cmd| seconds = cmd.to_s.split[0].to_i minutes = seconds / 60 hours = seconds / 3600 days = seconds / 86_400 seconds_dur = seconds days_dur = seconds_dur / 86_400 seconds_dur -= days_dur * 86_400 hours_dur = seconds_dur / 3600 seconds_dur -= hours_dur * 3600 minutes_dur = seconds_dur / 60 seconds_dur -= minutes_dur * 60 uptime_s = "#{days_dur}:#{hours_dur}:#{minutes_dur}:#{seconds_dur}" boot_time = Time.now - seconds Uptime.new( boot_time, uptime_s, seconds, minutes, hours, days ) end end
w(opts = {})
click to toggle source
# File lib/kanrisuru/core/system.rb, line 536 def w(opts = {}) users = opts[:users] command = Kanrisuru::Command.new('w -hi') command << users if Kanrisuru::Util.present?(users) execute(command) Kanrisuru::Result.new(command) do |cmd| result_string = cmd.raw_result.join rows = result_string.split("\n") rows.map do |row| values = *row.split(/\s+/, 8) UserLoggedIn.new( values[0], values[1], IPAddr.new(values[2]), values[3], values[4], values[5].to_f, values[6].to_f, values[7] ) end end end
who(opts = {})
click to toggle source
# File lib/kanrisuru/core/system.rb, line 564 def who(opts = {}) w(opts) end
Private Instance Methods
build_process_list(rows)
click to toggle source
# File lib/kanrisuru/core/system.rb, line 680 def build_process_list(rows) rows.map do |row| values = *row.split(/\s+/, 15) values.shift if values[0] == '' ProcessInfo.new( values[0].to_i, values[1], values[2].to_i, values[3], values[4].to_i, values[5].to_i, values[6].to_f, values[7].to_f, values[8], values[9].to_i, values[10].to_i, values[11], parse_policy_abbr(values[11]), values[12], values[13] ) end end
format_shutdown_time(time)
click to toggle source
# File lib/kanrisuru/core/system.rb, line 705 def format_shutdown_time(time) if time.instance_of?(Integer) || !/^[0-9]+$/.match(time).nil? "+#{time}" elsif !/^[0-9]{0,2}:[0-9]{0,2}$/.match(time).nil? || time == 'now' time else raise ArgumentError, 'Invalid time format' end end
parse_last_date(string)
click to toggle source
# File lib/kanrisuru/core/system.rb, line 644 def parse_last_date(string) tokens = string.split return if tokens.length < 4 month_abbr = tokens[1] day = tokens[2] timestamp = tokens[3] year = tokens[4] DateTime.parse("#{day} #{month_abbr} #{year} #{timestamp}") end
parse_lsof(line, char)
click to toggle source
# File lib/kanrisuru/core/system.rb, line 640 def parse_lsof(line, char) line.split(char, 2)[1] end
parse_policy_abbr(value)
click to toggle source
# File lib/kanrisuru/core/system.rb, line 657 def parse_policy_abbr(value) case value when '-' 'not reported' when 'TS' 'SCHED_OTHER' when 'FF' 'SCHED_FIFO' when 'RR' 'SCHED_RR' when 'B' 'SCHED_BATCH' when 'ISO' 'SCHED_ISO' when 'IDL' 'SCHED_IDLE' when 'DLN' 'SCHED_DEADLINE' else 'unknown value' end end