Alex Harvey
unread,Sep 20, 2012, 4:37:17 AM9/20/12Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to puppe...@googlegroups.com
I have made the following changes and tested to confirm it fixes the bug and tested on AIX 5.3 & 6.1, HP-UX 11.23, and Solaris 2.6 & 7. I have also created a fairly exhaustive set of RSpec tests I think.
I am still wondering if people will object to the fact I've removed the kstat method for Solaris - I think the uptime method is better and generally more reliable (I've seen kstat broken before a number of times in Solaris). That said, it's easy to leave the kstat in if people prefer.
Changes to RSpec tests / new tests -
# diff -u ./spec/unit/util/uptime_spec.rb.orig ./spec/unit/util/uptime_spec.rb
--- ./spec/unit/util/uptime_spec.rb.orig Wed Sep 19 22:26:16 2012
+++ ./spec/unit/util/uptime_spec.rb Thu Sep 20 17:18:31 2012
@@ -41,36 +41,50 @@
describe "nor is 'sysctl kern.boottime'" do
before :each do
- Facter::Util::Uptime.stubs(:uptime_sysctl_cmd).returns("cat \"#{@nonexistent_file}\"")
+ Facter::Util::Uptime.stubs(:uptime_proc_uptime).returns(false)
+ Facter::Util::Uptime.stubs(:uptime_sysctl).returns(false)
+ Facter.fact(:kernel).stubs(:value).returns('SunOS')
end
- it "should use 'kstat -p unix:::boot_time'" do
- kstat_output_file = my_fixture('kstat_boot_time') # unix:0:system_misc:boot_time 1236919980
- Facter::Util::Uptime.stubs(:uptime_kstat_cmd).returns("cat \"#{kstat_output_file}\"")
- Time.stubs(:now).returns Time.at(1236923580) #one hour later
- Facter::Util::Uptime.get_uptime_seconds_unix.should == 60 * 60
- end
+ describe "should use '/usr/bin/uptime'" do
+ # Note about uptime variations.
+ # Solaris (5.6, 5.7, 5.8, 5.9, 5.10 & 5.11) and HP-UX (11.00, 11.11, 11.23, 11.31) have time right justified at
+ # at 8 characters, and two spaces before 'up'.
+ # Solaris differs from all other Unices (and Linux) in that the plural/singular case of minutes/hours/days are
+ # written min(s)/hr(s)/day(s) instead of min/mins/hr/hrs etc., e.g. 1 min(s), 2 min(s) as opposed to
+ # 1 min, 2 mins, etc.
+ # AIX (4.3.3, 5.2, 5.3, 6.1) differs from other SysV Unices in that times are padded with a leading 0 in the
+ # hour column where necessary, and have AM/PM in uppercase, and there are three spaces before 'up'.
+ # Tru64 (4.0, 5.1) differs from other SysV Unices in that times are in 24 hour format, and there are no
+ # leading spaces.
+ # Linux (RHEL 5) differs from the Unices in that seconds are given in the time, time is right justified at
+ # 9 characters, one space before up.
+ test_cases = [
+ [' 4:42pm up 1 min(s), 0 users, load average: 0.95, 0.25, 0.09', 1*60],
+ [' 10:14pm up 3 hr(s), 0 users, load average: 0.00, 0.00, 0.00', 3*60*60 ],
+ [' 9:01pm up 1:47, 0 users, load average: 0.00, 0.00, 0.00', 1*60*60 + 47*60],
+ [' 1:56pm up 25 day(s), 2 users, load average: 0.59, 0.56, 0.50', 25*24*60*60 ],
+ [' 2:23pm up 25 day(s), 27 min(s), 2 users, load average: 0.49, 0.45, 0.46', 25*24*60*60 + 27*60],
+ [' 1:07pm up 174 day(s), 16 hr(s), 0 users, load average: 0.05, 0.04, 0.03', 174*24*60*60 + 16*60*60 ],
+ [' 8:59pm up 94 day(s), 3:17, 46 users, load average: 0.66, 0.67, 0.70', 94*24*60*60 + 3*60*60 + 17*60],
+ [' 02:42PM up 1 day, 39 mins, 0 users, load average: 1.49, 1.74, 1.80', 1*24*60*60 + 39*60],
+ [' 02:34PM up 621 days, 18 hrs, 0 users, load average: 2.67, 2.52, 2.56', 621*24*60*60 + 18*60*60 ],
+ [' 02:42PM up 41 days, 2:38, 0 users, load average: 0.38, 0.70, 0.55', 41*24*60*60 + 2*60*60 + 38*60],
+ [' 1:29pm up 485 days, 0 users, load average: 0.00, 0.01, 0.01', 485*24*60*60 ],
+ [' 3:30am up 108 days, 1 hr, 31 users, load average: 0.39, 0.40, 0.41', 108*24*60*60 + 1*60*60 ],
+ ['13:16 up 58 mins, 2 users, load average: 0.00, 0.02, 0.05', 58*60],
+ ['13:18 up 1 hr, 1 user, load average: 0.58, 0.23, 0.14', 1*60*60 ],
+ ['13:19 up 1:01, 1 user, load average: 0.10, 0.26, 0.21', 1*60*60 + 1*60],
+ ['15:56 up 152 days, 17 hrs, 0 users, load average: 0.01, 0.06, 0.07', 152*24*60*60 + 17*60*60 ],
+ [' 13:36:05 up 118 days, 1:15, 1 user, load average: 0.00, 0.00, 0.00', 118*24*60*60 + 1*60*60 + 15*60]
+ ]
- describe "nor is 'kstat -p unix:::boot_time'" do
- before :each do
- Facter::Util::Uptime.stubs(:uptime_kstat_cmd).returns("cat \"#{@nonexistent_file}\"")
- end
-
- it "should use 'who -b'" do
- who_b_output_file = my_fixture('who_b_boottime') # Aug 1 14:13
- Facter::Util::Uptime.stubs(:uptime_who_cmd).returns("cat \"#{who_b_output_file}\"")
- Time.stubs(:now).returns Time.parse("Aug 01 15:13") # one hour later
- Facter::Util::Uptime.get_uptime_seconds_unix.should == 60 * 60
- end
-
- describe "nor is 'who -b'" do
- before :each do
- Facter::Util::Uptime.stubs(:uptime_who_cmd).returns("cat \"#{@nonexistent_file}\"")
+ test_cases.each do |uptime_output, expected|
+ it "should return #{expected} for #{uptime_output}" do
+ Facter::Util::Resolution.stubs(:exec).with('/usr/bin/uptime 2>/dev/null').returns(uptime_output)
+ Facter.fact(:uptime_seconds).value.should == expected
end
-
- it "should return nil" do
- Facter::Util::Uptime.get_uptime_seconds_unix.should == nil
- end
end
end
end
# diff -u ./lib/facter/util/uptime.rb.orig ./lib/facter/util/uptime.rb
--- ./lib/facter/util/uptime.rb.orig Wed Sep 19 22:26:11 2012
+++ ./lib/facter/util/uptime.rb Thu Sep 20 18:28:01 2012
@@ -4,7 +4,7 @@
#
module Facter::Util::Uptime
def self.get_uptime_seconds_unix
- uptime_proc_uptime or uptime_sysctl or uptime_kstat or uptime_who_dash_b
+ uptime_proc_uptime or uptime_sysctl or uptime_uptime
end
def self.get_uptime_seconds_win
@@ -31,18 +31,33 @@
end
end
- def self.uptime_kstat
- if output = Facter::Util::Resolution.exec("#{uptime_kstat_cmd} 2>/dev/null")
- compute_uptime(Time.at(output.chomp.split(/\s/).last.to_i))
+ def self.uptime_uptime
+ if output = Facter::Util::Resolution.exec("#{uptime_uptime_cmd} 2>/dev/null")
+ up=0
+ if output =~ /(\d+) day(?:s|\(s\))?,\s+(\d+):(\d+)/
+ # Regexp handles Solaris, AIX, HP-UX, and Tru64.
+ # 'day(?:s|\(s\))?' says maybe 'day', 'days',
+ # or 'day(s)', and don't set $2.
+ up=86400*$1.to_i + 3600*$2.to_i + 60*$3.to_i
+ elsif output =~ /(\d+) day(?:s|\(s\))?,\s+(\d+) hr(?:s|\(s\))?,/
+ up=86400*$1.to_i + 3600*$2.to_i
+ elsif output =~ /(\d+) day(?:s|\(s\))?,\s+(\d+) min(?:s|\(s\))?,/
+ up=86400*$1.to_i + 60*$2.to_i
+ elsif output =~ /(\d+) day(?:s|\(s\))?,/
+ up=86400*$1.to_i
+ elsif output =~ /up\s+(\d+):(\d+),/
+ # must anchor to 'up' to avoid matching time of day
+ # at beginning of line.
+ up=3600*$1.to_i + 60*$2.to_i
+ elsif output =~ /(\d+) hr(?:s|\(s\))?,/
+ up=3600*$1.to_i
+ elsif output =~ /(\d+) min(?:s|\(s\))?,/
+ up=60*$1.to_i
+ end
+ up
end
end
- def self.uptime_who_dash_b
- if output = Facter::Util::Resolution.exec("#{uptime_who_cmd} 2>/dev/null")
- compute_uptime(Time.parse(output))
- end
- end
-
def self.compute_uptime(time)
(Time.now - time).to_i
end
@@ -55,11 +70,7 @@
'sysctl -n kern.boottime'
end
- def self.uptime_kstat_cmd
- 'kstat -p unix:::boot_time'
+ def self.uptime_uptime_cmd
+ "/usr/bin/uptime"
end
-
- def self.uptime_who_cmd
- 'who -b'
- end
end
If there are no objections I guess I should submit the change.