class SysInfo
SysInfo¶ ↑
A container for the platform specific system information. Portions of this code were originally from Amazon's EC2 AMI tools, specifically lib/platform.rb.
Constants
- ARCHITECTURES
- IMPLEMENTATIONS
- VERSION
Public Class Methods
# File lib/sysinfo.rb, line 78 def initialize @vm, @os, @impl, @arch = find_platform_info @hostname, @ipaddress_internal, @uptime = find_network_info @ruby = RUBY_VERSION.split('.').collect { |v| v.to_i } @user = getpwattr(:name) || ENV['USER'] require 'Win32API' if @os == :windows && @vm == :ruby end
Public Instance Methods
Return the hostname for the local machine
# File lib/sysinfo.rb, line 115 def find_hostname; Socket.gethostname; end
Return the local IP address which receives external traffic from: coderrr.wordpress.com/2008/05/28/get-your-local-ip-address/ NOTE: This does not open a connection to the IP address.
# File lib/sysinfo.rb, line 136 def find_ipaddress_internal # turn off reverse DNS resolution temporarily orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true UDPSocket.open {|s| s.connect('65.74.177.129', 1); s.addr.last } # GitHub IP ensure Socket.do_not_reverse_lookup = orig end
Returns [hostname, ipaddr (internal), uptime]
# File lib/sysinfo.rb, line 103 def find_network_info hostname, ipaddr, uptime = :unknown, :unknown, :unknown begin hostname = find_hostname ipaddr = find_ipaddress_internal uptime = find_uptime rescue => ex # Be silent! end [hostname, ipaddr, uptime] end
Returns [vm, os, impl, arch]
# File lib/sysinfo.rb, line 87 def find_platform_info vm, os, impl, arch = :ruby, :unknown, :unknown, :unknow IMPLEMENTATIONS.each do |r, o, i| next unless RUBY_PLATFORM =~ r os, impl = [o, i] break end ARCHITECTURES.each do |r, a| next unless RUBY_PLATFORM =~ r arch = a break end os == :java ? guess_java : [vm, os, impl, arch] end
Returns the local uptime in hours. Use Win32API in Windows, 'sysctl -b kern.boottime' os osx, and 'who -b' on unix. Based on Ruby Quiz solutions by: Matthias Reitinger On Windows, see also: net statistics server
# File lib/sysinfo.rb, line 121 def find_uptime hours = 0 begin seconds = execute_platform_specific("find_uptime") || 0 hours = seconds / 3600 # seconds to hours rescue => ex #puts ex.message # TODO: implement debug? end hours end
Returns the path to the current user's home directory
# File lib/sysinfo.rb, line 153 def home; execute_platform_specific(:home); end
Returns the environment paths as an Array
# File lib/sysinfo.rb, line 151 def paths; execute_platform_specific(:paths); end
Returns a String of the full platform descriptor in the format:
VM-OS-IMPL-ARCH e.g. java-unix-osx-x86_64
# File lib/sysinfo.rb, line 146 def platform "#{@vm}-#{@os}-#{@impl}-#{@arch}" end
Returns the name of the current shell
# File lib/sysinfo.rb, line 155 def shell; execute_platform_specific(:shell); end
Returns the path to the current temp directory
# File lib/sysinfo.rb, line 157 def tmpdir; execute_platform_specific(:tmpdir); end
Private Instance Methods
Look for and execute a platform specific method. The name of the method
will be in the format: dtype-VM-OS-IMPL
. e.g. #find_uptime_ruby_unix_osx
# File lib/sysinfo.rb, line 165 def execute_platform_specific(dtype) criteria = [@vm, @os, @impl] while !criteria.empty? meth = [dtype, criteria].join('_').to_sym return self.send(meth) if SysInfo.private_method_defined?(meth) criteria.pop end raise "#{dtype}_#{@vm}_#{@os}_#{@impl} not implemented" end
Ya, this is kinda wack. Ruby -> Java -> Kernel32. See: www.oreillynet.com/ruby/blog/2008/01/jruby_meets_the_windows_api_1.html
msdn.microsoft.com/en-us/library/ms724408(VS.85).aspx Ruby 1.9.1: Win32API is now deprecated in favor of using the DL library.
# File lib/sysinfo.rb, line 208 def find_uptime_java_windows_windows kernel32 = com.sun.jna.NativeLibrary.getInstance('kernel32') buf = java.nio.ByteBuffer.allocate(256) (kernel32.getFunction('GetTickCount').invokeInt([256, buf].to_java).to_f / 1000).to_f end
This should work for most unix flavours.
# File lib/sysinfo.rb, line 224 def find_uptime_ruby_unix # who is sloooooow. Use File.read('/proc/uptime') (Time.now.to_i - Time.parse(%x`who -b 2>/dev/null`).to_f) end
# File lib/sysinfo.rb, line 218 def find_uptime_ruby_unix_osx # This is faster than "who" and could work on BSD also. (Time.now.to_f - Time.at(%x`sysctl -b kern.boottime 2>/dev/null`.unpack('L').first).to_f).to_f end
# File lib/sysinfo.rb, line 213 def find_uptime_ruby_windows_windows # Win32API is required in self.guess getTickCount = Win32API.new("kernel32", "GetTickCount", nil, 'L') ((getTickCount.call()).to_f / 1000).to_f end
Returns a named attribute of the user's /etc/password entry, or nil. As an example, `getpwdattr(:home)` will return the user's home directory without relying on ENV being present.
# File lib/sysinfo.rb, line 273 def getpwattr(pwattr) passwd = Etc.getpwuid(Process::Sys.getuid) || {} passwd[pwattr] end
Determine the values for vm, os, impl, and arch when running on Java.
# File lib/sysinfo.rb, line 231 def guess_java vm, os, impl, arch = :java, :unknown, :unknown, :unknown require 'java' include_class java.lang.System unless defined?(System) osname = System.getProperty("os.name") IMPLEMENTATIONS.each do |r, o, i| next unless osname =~ r os, impl = [o, i] break end osarch = System.getProperty("os.arch") ARCHITECTURES.each do |r, a| next unless osarch =~ r arch = a break end [vm, os, impl, arch] end
# File lib/sysinfo.rb, line 196 def home_java if @impl == :windows File.expand_path(ENV['USERPROFILE']) else File.expand_path(getpwattr(:dir)) end end
# File lib/sysinfo.rb, line 194 def home_ruby_unix; File.expand_path(getpwattr(:dir)); end
# File lib/sysinfo.rb, line 195 def home_ruby_windows; File.expand_path(ENV['USERPROFILE']); end
Returns the local IP address based on the hostname. According to coderrr (see comments on blog link above), this implementation doesn't guarantee that it will return the address for the interface external traffic goes through. It's also possible the hostname isn't resolvable to the local IP.
NOTE: This code predates the current ip_address_internal. It was just as well but the other code is cleaner. I'm keeping this old version here for now.
# File lib/sysinfo.rb, line 260 def ip_address_internal_alt ipaddr = :unknown begin saddr = Socket.getaddrinfo( Socket.gethostname, nil, Socket::AF_UNSPEC, Socket::SOCK_STREAM, nil, Socket::AI_CANONNAME) ipaddr = saddr.select{|type| type[0] == 'AF_INET' }[0][3] rescue => ex end ipaddr end
# File lib/sysinfo.rb, line 177 def paths_java delim = @impl == :windows ? ';' : ':' (ENV['PATH'] || '').split(delim) end
# File lib/sysinfo.rb, line 175 def paths_ruby_unix; (ENV['PATH'] || '').split(':'); end
# File lib/sysinfo.rb, line 176 def paths_ruby_windows; (ENV['PATH'] || '').split(';'); end
# File lib/sysinfo.rb, line 189 def shell_ruby_unix; (ENV['SHELL'] || getpwattr(:shell) || 'bash').to_sym; end
# File lib/sysinfo.rb, line 190 def shell_ruby_windows; :dos; end
# File lib/sysinfo.rb, line 184 def tmpdir_java default = @impl == :windows ? 'C:\temp' : '/tmp' (Dir.tmpdir || default) end
# File lib/sysinfo.rb, line 182 def tmpdir_ruby_unix; (Dir.tmpdir || '/tmp'); end
# File lib/sysinfo.rb, line 183 def tmpdir_ruby_windows; (Dir.tmpdir || 'C:\temp'); end