lib/facter/util/facts/uptime_parser.rb
# frozen_string_literal: true
require 'time'
module Facter
module Util
module Facts
class UptimeParser
SECS_IN_A_DAY = 86_400
SECS_IN_AN_HOUR = 3_600
SECS_IN_A_MINUTE = 60
@log = Facter::Log.new(self)
class << self
def uptime_seconds_unix
uptime_proc_uptime || uptime_sysctl || uptime_executable
end
private
def uptime_proc_uptime
output = Facter::Core::Execution.execute("/bin/cat #{uptime_file}", logger: @log)
output.chomp.split(' ').first.to_i unless output.empty?
end
def uptime_sysctl
output = Facter::Core::Execution.execute("sysctl -n #{uptime_sysctl_variable}", logger: @log)
compute_uptime(Time.at(output.match(/\d+/)[0].to_i)) unless output.empty?
end
def uptime_executable
output = Facter::Core::Execution.execute(uptime_executable_cmd, logger: @log)
return unless output
up = 0
output_calculator_methods.find { |method| up = send(method, output) }
up || 0
end
def uptime_file
'/proc/uptime'
end
def uptime_sysctl_variable
'kern.boottime'
end
def uptime_executable_cmd
'uptime'
end
def output_calculator_methods
%i[
calculate_days_hours_minutes
calculate_days_hours
calculate_days_minutes
calculate_days
calculate_hours_minutes
calculate_hours
calculate_minutes
]
end
def compute_uptime(time)
(Time.now - time).to_i
end
# Regexp handles Solaris, AIX, HP-UX, and Tru64.
# 'day(?:s|\(s\))?' says maybe 'day', 'days',
# or 'day(s)', and don't set $2.
def calculate_days_hours_minutes(output)
return unless output =~ /(\d+) day(?:s|\(s\))?,?\s+(\d+):-?(\d+)/
SECS_IN_A_DAY * Regexp.last_match(1).to_i +
SECS_IN_AN_HOUR * Regexp.last_match(2).to_i +
SECS_IN_A_MINUTE * Regexp.last_match(3).to_i
end
def calculate_days_hours(output)
return unless output =~ /(\d+) day(?:s|\(s\))?,\s+(\d+) hr(?:s|\(s\))?,/
SECS_IN_A_DAY * Regexp.last_match(1).to_i +
SECS_IN_AN_HOUR * Regexp.last_match(2).to_i
end
def calculate_days_minutes(output)
return unless output =~ /(\d+) day(?:s|\(s\))?,\s+(\d+) min(?:s|\(s\))?,/
SECS_IN_A_DAY * Regexp.last_match(1).to_i +
SECS_IN_A_MINUTE * Regexp.last_match(2).to_i
end
def calculate_days(output)
return unless output =~ /(\d+) day(?:s|\(s\))?,/
SECS_IN_A_DAY * Regexp.last_match(1).to_i
end
# must anchor to 'up' to avoid matching time of day
# at beginning of line. Certain versions of uptime on
# Solaris may insert a '-' into the minutes field.
def calculate_hours_minutes(output)
return unless output =~ /up\s+(\d+):-?(\d+),/
SECS_IN_AN_HOUR * Regexp.last_match(1).to_i +
SECS_IN_A_MINUTE * Regexp.last_match(2).to_i
end
def calculate_hours(output)
return unless output =~ /(\d+) hr(?:s|\(s\))?,/
SECS_IN_AN_HOUR * Regexp.last_match(1).to_i
end
def calculate_minutes(output)
return unless output =~ /(\d+) min(?:s|\(s\))?,/
SECS_IN_A_MINUTE * Regexp.last_match(1).to_i
end
end
end
end
end
end