From 47a8647496b4c596587814da306c544a671118b0 Mon Sep 17 00:00:00 2001 From: Sourav Goswami Date: Sat, 21 Nov 2020 13:09:33 +0530 Subject: [PATCH 1/8] Added parse_lsb_release --- lib/os.rb | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/lib/os.rb b/lib/os.rb index 4228093..b47ccf0 100644 --- a/lib/os.rb +++ b/lib/os.rb @@ -283,18 +283,11 @@ def self.app_config_path(name) end def self.parse_os_release - if OS.linux? && File.exist?('/etc/os-release') - output = {} + parse_release('/etc/os-release') + end - File.read('/etc/os-release').each_line do |line| - parsed_line = line.chomp.tr('"', '').split('=') - next if parsed_line.empty? - output[parsed_line[0].to_sym] = parsed_line[1] - end - output - else - raise "File /etc/os-release doesn't exists or not Linux" - end + def self.parse_lsb_release + parse_release('/etc/lsb-release') end class << self @@ -314,4 +307,16 @@ def self.hwprefs_available? `which hwprefs` != '' end + def self.parse_release(file) + if OS.linux? && File.readable?(file) + File.readlines(file).reduce({}) do |output, line| + parsed_line = line.strip.delete(?").split('=') + next if parsed_line.empty? + output.merge(parsed_line[0].to_sym => parsed_line[1]) + end + else + raise "File #{file} doesn't exist or not Linux" + end +end + end From 0aeacd7f0ad82a7ae665de8d807631375cd92d8f Mon Sep 17 00:00:00 2001 From: Sourav Goswami Date: Sat, 21 Nov 2020 13:13:34 +0530 Subject: [PATCH 2/8] Linux - Removed bash script to detect cpu, and added pure Ruby solution instead --- lib/os.rb | 623 +++++++++++++++++++++++++++--------------------------- 1 file changed, 311 insertions(+), 312 deletions(-) diff --git a/lib/os.rb b/lib/os.rb index b47ccf0..49a3e3f 100644 --- a/lib/os.rb +++ b/lib/os.rb @@ -5,318 +5,317 @@ # treats cygwin as linux # also treats IronRuby on mono as...linux class OS - attr_reader :config - - def self.config - @config ||= RbConfig::CONFIG - end - - # true if on windows [and/or jruby] - # false if on linux or cygwin on windows - - def self.windows? - @windows ||= begin - if RUBY_PLATFORM =~ /cygwin/ # i386-cygwin - false - elsif ENV['OS'] == 'Windows_NT' - true - else - false - end - end - - end - - # true for linux, os x, cygwin - def self.posix? - @posix ||= - begin - if OS.windows? - begin - begin - # what if we're on interix... - # untested, of course - Process.wait fork{} - true - rescue NotImplementedError, NoMethodError - false - end - end - else - # assume non windows is posix - true - end - end - - end - - # true for linux, false for windows, os x, cygwin - def self.linux? - if (host_os =~ /linux/) - true - else - false - end - end - - def self.freebsd? - if (host_os =~ /freebsd/) - true - else - false - end - end - - def self.iron_ruby? - @iron_ruby ||= begin - if defined?(RUBY_ENGINE) && (RUBY_ENGINE == 'ironruby') - true - else - false - end - end - end - - def self.bits - @bits ||= begin - if host_cpu =~ /_64$/ || RUBY_PLATFORM =~ /x86_64/ - 64 - elsif RUBY_PLATFORM == 'java' && ENV_JAVA['sun.arch.data.model'] # "32" or "64":http://www.ruby-forum.com/topic/202173#880613 - ENV_JAVA['sun.arch.data.model'].to_i - elsif host_cpu == 'i386' - 32 - elsif host_os =~ /32$/ # mingw32, mswin32 - 32 - else # cygwin only...I think - if 1.size == 8 - 64 - else - 32 - end - end - end - end - - - def self.java? - @java ||= begin - if RUBY_PLATFORM =~ /java/ - true - else - false - end - end - end - - def self.ruby_bin - @ruby_exe ||= begin - File::join(config['bindir'], config['ruby_install_name']) + config['EXEEXT'] - end - end - - def self.mac? - @mac = begin - if host_os =~ /darwin/ - true - else - false - end - end - end - - def self.osx? - mac? - end - - def self.x? - mac? - end - - - # amount of memory the current process "is using", in RAM - # (doesn't include any swap memory that it may be using, just that in actual RAM) - # raises 'unknown' on jruby currently - def self.rss_bytes - # attempt to do this in a jruby friendly way - if OS::Underlying.windows? - # MRI, Java, IronRuby, Cygwin - if OS.java? - # no win32ole on 1.5.x, so leave here for compatibility...maybe for awhile :P - require 'java' - mem_bean = java.lang.management.ManagementFactory.getMemoryMXBean - mem_bean.heap_memory_usage.used + mem_bean.non_heap_memory_usage.used - else - wmi = nil - begin - require 'win32ole' - wmi = WIN32OLE.connect("winmgmts://") - rescue LoadError, NoMethodError => e # NoMethod for IronRuby currently [sigh] - raise 'rss unknown for this platform ' + e.to_s - end - processes = wmi.ExecQuery("select * from win32_process where ProcessId = #{Process.pid}") - memory_used = nil - # only allow for one... - for process in processes - raise if memory_used - memory_used = process.WorkingSetSize.to_i - end - memory_used - end - elsif OS.posix? # linux [though I've heard it works in OS X] - `ps -o rss= -p #{Process.pid}`.to_i # in kilobytes - else - raise 'unknown rss for this platform' - end - end - - class Underlying - - def self.bsd? - OS.osx? - end - - def self.windows? - ENV['OS'] == 'Windows_NT' - end - - def self.linux? - OS.host_os =~ /linux/ ? true : false - end - - def self.docker? - system('grep -q docker /proc/self/cgroup') if OS.linux? - end - - end - - def self.cygwin? - @cygwin = begin - if RUBY_PLATFORM =~ /-cygwin/ - true - else - false - end - end - end - - def self.dev_null # File::NULL in 1.9.3+ - @dev_null ||= begin - if OS.windows? - "NUL" - else - "/dev/null" - end - end - end - - # provides easy way to see the relevant config entries - def self.report - relevant_keys = [ - 'arch', - 'host', - 'host_cpu', - 'host_os', - 'host_vendor', - 'target', - 'target_cpu', - 'target_os', - 'target_vendor', - ] - RbConfig::CONFIG.reject {|key, val| !relevant_keys.include? key }.merge({'RUBY_PLATFORM' => RUBY_PLATFORM}).to_yaml - end - - def self.cpu_count - @cpu_count ||= - case RUBY_PLATFORM - when /darwin9/ - `hwprefs cpu_count`.to_i - when /darwin10/ - (hwprefs_available? ? `hwprefs thread_count` : `sysctl -n hw.ncpu`).to_i - when /linux/ - `cat /proc/cpuinfo | grep processor | wc -l`.to_i - when /freebsd/ - `sysctl -n hw.ncpu`.to_i - else - if RbConfig::CONFIG['host_os'] =~ /darwin/ - (hwprefs_available? ? `hwprefs thread_count` : `sysctl -n hw.ncpu`).to_i - elsif self.windows? - # ENV counts hyper threaded...not good. - # out = ENV['NUMBER_OF_PROCESSORS'].to_i - require 'win32ole' - wmi = WIN32OLE.connect("winmgmts://") - cpu = wmi.ExecQuery("select NumberOfCores from Win32_Processor") # don't count hyper-threaded in this - cpu.to_enum.first.NumberOfCores - else - raise 'unknown platform processor_count' - end - end - end - - def self.open_file_command - if OS.doze? || OS.cygwin? - "start" - elsif OS.mac? - "open" - else - # linux...what about cygwin? - "xdg-open" - end - - end - - def self.app_config_path(name) - if OS.doze? - if ENV['LOCALAPPDATA'] - return File.join(ENV['LOCALAPPDATA'], name) - end - - File.join ENV['USERPROFILE'], 'Local Settings', 'Application Data', name - elsif OS.mac? - File.join ENV['HOME'], 'Library', 'Application Support', name - else - if ENV['XDG_CONFIG_HOME'] - return File.join(ENV['XDG_CONFIG_HOME'], name) - end - - File.join ENV['HOME'], '.config', name - end - end - - def self.parse_os_release - parse_release('/etc/os-release') - end - - def self.parse_lsb_release - parse_release('/etc/lsb-release') - end - - class << self - alias :doze? :windows? # a joke name but I use it and like it :P - alias :jruby? :java? - - # delegators for relevant config values - %w(host host_cpu host_os).each do |method_name| - define_method(method_name) { config[method_name] } - end - - end - - private - - def self.hwprefs_available? - `which hwprefs` != '' - end - - def self.parse_release(file) - if OS.linux? && File.readable?(file) - File.readlines(file).reduce({}) do |output, line| - parsed_line = line.strip.delete(?").split('=') - next if parsed_line.empty? - output.merge(parsed_line[0].to_sym => parsed_line[1]) - end - else - raise "File #{file} doesn't exist or not Linux" - end + attr_reader :config + + def self.config + @config ||= RbConfig::CONFIG + end + + # true if on windows [and/or jruby] + # false if on linux or cygwin on windows + + def self.windows? + @windows ||= begin + if RUBY_PLATFORM =~ /cygwin/ # i386-cygwin + false + elsif ENV['OS'] == 'Windows_NT' + true + else + false + end + end + + end + + # true for linux, os x, cygwin + def self.posix? + @posix ||= + begin + if OS.windows? + begin + begin + # what if we're on interix... + # untested, of course + Process.wait fork{} + true + rescue NotImplementedError, NoMethodError + false + end + end + else + # assume non windows is posix + true + end + end + + end + + # true for linux, false for windows, os x, cygwin + def self.linux? + if (host_os =~ /linux/) + true + else + false + end + end + + def self.freebsd? + if (host_os =~ /freebsd/) + true + else + false + end + end + + def self.iron_ruby? + @iron_ruby ||= begin + if defined?(RUBY_ENGINE) && (RUBY_ENGINE == 'ironruby') + true + else + false + end + end + end + + def self.bits + @bits ||= begin + if host_cpu =~ /_64$/ || RUBY_PLATFORM =~ /x86_64/ + 64 + elsif RUBY_PLATFORM == 'java' && ENV_JAVA['sun.arch.data.model'] # "32" or "64":http://www.ruby-forum.com/topic/202173#880613 + ENV_JAVA['sun.arch.data.model'].to_i + elsif host_cpu == 'i386' + 32 + elsif host_os =~ /32$/ # mingw32, mswin32 + 32 + else # cygwin only...I think + if 1.size == 8 + 64 + else + 32 + end + end + end + end + + + def self.java? + @java ||= begin + if RUBY_PLATFORM =~ /java/ + true + else + false + end + end + end + + def self.ruby_bin + @ruby_exe ||= begin + File::join(config['bindir'], config['ruby_install_name']) + config['EXEEXT'] + end + end + + def self.mac? + @mac = begin + if host_os =~ /darwin/ + true + else + false + end + end + end + + def self.osx? + mac? + end + + def self.x? + mac? + end + + + # amount of memory the current process "is using", in RAM + # (doesn't include any swap memory that it may be using, just that in actual RAM) + # raises 'unknown' on jruby currently + def self.rss_bytes + # attempt to do this in a jruby friendly way + if OS::Underlying.windows? + # MRI, Java, IronRuby, Cygwin + if OS.java? + # no win32ole on 1.5.x, so leave here for compatibility...maybe for awhile :P + require 'java' + mem_bean = java.lang.management.ManagementFactory.getMemoryMXBean + mem_bean.heap_memory_usage.used + mem_bean.non_heap_memory_usage.used + else + wmi = nil + begin + require 'win32ole' + wmi = WIN32OLE.connect("winmgmts://") + rescue LoadError, NoMethodError => e # NoMethod for IronRuby currently [sigh] + raise 'rss unknown for this platform ' + e.to_s + end + processes = wmi.ExecQuery("select * from win32_process where ProcessId = #{Process.pid}") + memory_used = nil + # only allow for one... + for process in processes + raise if memory_used + memory_used = process.WorkingSetSize.to_i + end + memory_used + end + elsif OS.posix? # linux [though I've heard it works in OS X] + `ps -o rss= -p #{Process.pid}`.to_i # in kilobytes + else + raise 'unknown rss for this platform' + end + end + + class Underlying + + def self.bsd? + OS.osx? + end + + def self.windows? + ENV['OS'] == 'Windows_NT' + end + + def self.linux? + OS.host_os =~ /linux/ ? true : false + end + + def self.docker? + system('grep -q docker /proc/self/cgroup') if OS.linux? + end + + end + + def self.cygwin? + @cygwin = begin + if RUBY_PLATFORM =~ /-cygwin/ + true + else + false + end + end + end + + def self.dev_null # File::NULL in 1.9.3+ + @dev_null ||= begin + if OS.windows? + "NUL" + else + "/dev/null" + end + end + end + + # provides easy way to see the relevant config entries + def self.report + relevant_keys = [ + 'arch', + 'host', + 'host_cpu', + 'host_os', + 'host_vendor', + 'target', + 'target_cpu', + 'target_os', + 'target_vendor', + ] + RbConfig::CONFIG.reject {|key, val| !relevant_keys.include? key }.merge({'RUBY_PLATFORM' => RUBY_PLATFORM}).to_yaml + end + + def self.cpu_count + @cpu_count ||= + case RUBY_PLATFORM + when /darwin9/ + `hwprefs cpu_count`.to_i + when /darwin10/ + (hwprefs_available? ? `hwprefs thread_count` : `sysctl -n hw.ncpu`).to_i + when /linux/ + IO.readlines('/proc/cpuinfo').count { |x| x[/^processor/] } + when /freebsd/ + `sysctl -n hw.ncpu`.to_i + else + if RbConfig::CONFIG['host_os'] =~ /darwin/ + (hwprefs_available? ? `hwprefs thread_count` : `sysctl -n hw.ncpu`).to_i + elsif self.windows? + # ENV counts hyper threaded...not good. + # out = ENV['NUMBER_OF_PROCESSORS'].to_i + require 'win32ole' + wmi = WIN32OLE.connect("winmgmts://") + cpu = wmi.ExecQuery("select NumberOfCores from Win32_Processor") # don't count hyper-threaded in this + cpu.to_enum.first.NumberOfCores + else + raise 'unknown platform processor_count' + end + end + end + + def self.open_file_command + if OS.doze? || OS.cygwin? + "start" + elsif OS.mac? + "open" + else + # linux...what about cygwin? + "xdg-open" + end + end + + def self.app_config_path(name) + if OS.doze? + if ENV['LOCALAPPDATA'] + return File.join(ENV['LOCALAPPDATA'], name) + end + + File.join ENV['USERPROFILE'], 'Local Settings', 'Application Data', name + elsif OS.mac? + File.join ENV['HOME'], 'Library', 'Application Support', name + else + if ENV['XDG_CONFIG_HOME'] + return File.join(ENV['XDG_CONFIG_HOME'], name) + end + + File.join ENV['HOME'], '.config', name + end + end + + def self.parse_os_release + parse_release('/etc/os-release') + end + + def self.parse_lsb_release + parse_release('/etc/lsb-release') + end + + class << self + alias :doze? :windows? # a joke name but I use it and like it :P + alias :jruby? :java? + + # delegators for relevant config values + %w(host host_cpu host_os).each do |method_name| + define_method(method_name) { config[method_name] } + end + + end + + private + + def self.hwprefs_available? + `which hwprefs` != '' + end + + def self.parse_release(file) + if OS.linux? && File.readable?(file) + File.readlines(file).reduce({}) do |output, line| + parsed_line = line.strip.delete(?").split('=') + next if parsed_line.empty? + output.merge(parsed_line[0].to_sym => parsed_line[1]) + end + else + raise "File #{file} doesn't exist or not Linux" + end end end From 809ac0df6e87ae925a9879cac09d5ae905e868bf Mon Sep 17 00:00:00 2001 From: Sourav Goswami Date: Sat, 21 Nov 2020 13:30:07 +0530 Subject: [PATCH 3/8] Added OS.ipv4_private --- README.md | 11 +- lib/os.rb | 630 +++++++++++++++++++++++++++--------------------------- 2 files changed, 324 insertions(+), 317 deletions(-) diff --git a/README.md b/README.md index 19f86e4..81f777a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -The OS gem allows for some easy telling if you're on windows or not. +The OS gem allows for some easy telling if you're on windows or not. ```ruby require 'os' @@ -24,12 +24,15 @@ require 'os' >> OS.dev_null => "NUL" # or "/dev/null" depending on which platform +>> OS.ipv4_private +=> "192.168.0.106" + >> OS.rss_bytes => 12300033 # number of rss bytes this process is using currently. Basically "total in memory footprint" (doesn't include RAM used by the process that's in swap/page file) >> puts OS.report ==> # a yaml report of helpful values ---- +--- arch: x86_64-darwin10.6.0 target_os: darwin10.6.0 target_vendor: apple @@ -41,7 +44,7 @@ host_cpu: i386 host: i386-apple-darwin10.6.0 RUBY_PLATFORM: x86_64-darwin10.6.0 ->> OS.cpu_count +>> OS.cpu_count => 2 # number of cores, doesn't include hyper-threaded cores. >> OS.open_file_command @@ -72,7 +75,7 @@ RUBY_PLATFORM: x86_64-darwin10.6.0 :VERSION_CODENAME=>"bionic", :UBUNTU_CODENAME=>"bionic"} ``` - + If there are any other features you'd like, let me know, I'll do what I can to add them :) http://github.com/rdp/os for feedback et al diff --git a/lib/os.rb b/lib/os.rb index 49a3e3f..80cf135 100644 --- a/lib/os.rb +++ b/lib/os.rb @@ -5,317 +5,321 @@ # treats cygwin as linux # also treats IronRuby on mono as...linux class OS - attr_reader :config - - def self.config - @config ||= RbConfig::CONFIG - end - - # true if on windows [and/or jruby] - # false if on linux or cygwin on windows - - def self.windows? - @windows ||= begin - if RUBY_PLATFORM =~ /cygwin/ # i386-cygwin - false - elsif ENV['OS'] == 'Windows_NT' - true - else - false - end - end - - end - - # true for linux, os x, cygwin - def self.posix? - @posix ||= - begin - if OS.windows? - begin - begin - # what if we're on interix... - # untested, of course - Process.wait fork{} - true - rescue NotImplementedError, NoMethodError - false - end - end - else - # assume non windows is posix - true - end - end - - end - - # true for linux, false for windows, os x, cygwin - def self.linux? - if (host_os =~ /linux/) - true - else - false - end - end - - def self.freebsd? - if (host_os =~ /freebsd/) - true - else - false - end - end - - def self.iron_ruby? - @iron_ruby ||= begin - if defined?(RUBY_ENGINE) && (RUBY_ENGINE == 'ironruby') - true - else - false - end - end - end - - def self.bits - @bits ||= begin - if host_cpu =~ /_64$/ || RUBY_PLATFORM =~ /x86_64/ - 64 - elsif RUBY_PLATFORM == 'java' && ENV_JAVA['sun.arch.data.model'] # "32" or "64":http://www.ruby-forum.com/topic/202173#880613 - ENV_JAVA['sun.arch.data.model'].to_i - elsif host_cpu == 'i386' - 32 - elsif host_os =~ /32$/ # mingw32, mswin32 - 32 - else # cygwin only...I think - if 1.size == 8 - 64 - else - 32 - end - end - end - end - - - def self.java? - @java ||= begin - if RUBY_PLATFORM =~ /java/ - true - else - false - end - end - end - - def self.ruby_bin - @ruby_exe ||= begin - File::join(config['bindir'], config['ruby_install_name']) + config['EXEEXT'] - end - end - - def self.mac? - @mac = begin - if host_os =~ /darwin/ - true - else - false - end - end - end - - def self.osx? - mac? - end - - def self.x? - mac? - end - - - # amount of memory the current process "is using", in RAM - # (doesn't include any swap memory that it may be using, just that in actual RAM) - # raises 'unknown' on jruby currently - def self.rss_bytes - # attempt to do this in a jruby friendly way - if OS::Underlying.windows? - # MRI, Java, IronRuby, Cygwin - if OS.java? - # no win32ole on 1.5.x, so leave here for compatibility...maybe for awhile :P - require 'java' - mem_bean = java.lang.management.ManagementFactory.getMemoryMXBean - mem_bean.heap_memory_usage.used + mem_bean.non_heap_memory_usage.used - else - wmi = nil - begin - require 'win32ole' - wmi = WIN32OLE.connect("winmgmts://") - rescue LoadError, NoMethodError => e # NoMethod for IronRuby currently [sigh] - raise 'rss unknown for this platform ' + e.to_s - end - processes = wmi.ExecQuery("select * from win32_process where ProcessId = #{Process.pid}") - memory_used = nil - # only allow for one... - for process in processes - raise if memory_used - memory_used = process.WorkingSetSize.to_i - end - memory_used - end - elsif OS.posix? # linux [though I've heard it works in OS X] - `ps -o rss= -p #{Process.pid}`.to_i # in kilobytes - else - raise 'unknown rss for this platform' - end - end - - class Underlying - - def self.bsd? - OS.osx? - end - - def self.windows? - ENV['OS'] == 'Windows_NT' - end - - def self.linux? - OS.host_os =~ /linux/ ? true : false - end - - def self.docker? - system('grep -q docker /proc/self/cgroup') if OS.linux? - end - - end - - def self.cygwin? - @cygwin = begin - if RUBY_PLATFORM =~ /-cygwin/ - true - else - false - end - end - end - - def self.dev_null # File::NULL in 1.9.3+ - @dev_null ||= begin - if OS.windows? - "NUL" - else - "/dev/null" - end - end - end - - # provides easy way to see the relevant config entries - def self.report - relevant_keys = [ - 'arch', - 'host', - 'host_cpu', - 'host_os', - 'host_vendor', - 'target', - 'target_cpu', - 'target_os', - 'target_vendor', - ] - RbConfig::CONFIG.reject {|key, val| !relevant_keys.include? key }.merge({'RUBY_PLATFORM' => RUBY_PLATFORM}).to_yaml - end - - def self.cpu_count - @cpu_count ||= - case RUBY_PLATFORM - when /darwin9/ - `hwprefs cpu_count`.to_i - when /darwin10/ - (hwprefs_available? ? `hwprefs thread_count` : `sysctl -n hw.ncpu`).to_i - when /linux/ - IO.readlines('/proc/cpuinfo').count { |x| x[/^processor/] } - when /freebsd/ - `sysctl -n hw.ncpu`.to_i - else - if RbConfig::CONFIG['host_os'] =~ /darwin/ - (hwprefs_available? ? `hwprefs thread_count` : `sysctl -n hw.ncpu`).to_i - elsif self.windows? - # ENV counts hyper threaded...not good. - # out = ENV['NUMBER_OF_PROCESSORS'].to_i - require 'win32ole' - wmi = WIN32OLE.connect("winmgmts://") - cpu = wmi.ExecQuery("select NumberOfCores from Win32_Processor") # don't count hyper-threaded in this - cpu.to_enum.first.NumberOfCores - else - raise 'unknown platform processor_count' - end - end - end - - def self.open_file_command - if OS.doze? || OS.cygwin? - "start" - elsif OS.mac? - "open" - else - # linux...what about cygwin? - "xdg-open" - end - end - - def self.app_config_path(name) - if OS.doze? - if ENV['LOCALAPPDATA'] - return File.join(ENV['LOCALAPPDATA'], name) - end - - File.join ENV['USERPROFILE'], 'Local Settings', 'Application Data', name - elsif OS.mac? - File.join ENV['HOME'], 'Library', 'Application Support', name - else - if ENV['XDG_CONFIG_HOME'] - return File.join(ENV['XDG_CONFIG_HOME'], name) - end - - File.join ENV['HOME'], '.config', name - end - end - - def self.parse_os_release - parse_release('/etc/os-release') - end - - def self.parse_lsb_release - parse_release('/etc/lsb-release') - end - - class << self - alias :doze? :windows? # a joke name but I use it and like it :P - alias :jruby? :java? - - # delegators for relevant config values - %w(host host_cpu host_os).each do |method_name| - define_method(method_name) { config[method_name] } - end - - end - - private - - def self.hwprefs_available? - `which hwprefs` != '' - end - - def self.parse_release(file) - if OS.linux? && File.readable?(file) - File.readlines(file).reduce({}) do |output, line| - parsed_line = line.strip.delete(?").split('=') - next if parsed_line.empty? - output.merge(parsed_line[0].to_sym => parsed_line[1]) - end - else - raise "File #{file} doesn't exist or not Linux" - end -end - + attr_reader :config + + def self.config + @config ||= RbConfig::CONFIG + end + + # true if on windows [and/or jruby] + # false if on linux or cygwin on windows + + def self.windows? + @windows ||= begin + if RUBY_PLATFORM =~ /cygwin/ # i386-cygwin + false + elsif ENV['OS'] == 'Windows_NT' + true + else + false + end + end + + end + + # true for linux, os x, cygwin + def self.posix? + @posix ||= + begin + if OS.windows? + begin + begin + # what if we're on interix... + # untested, of course + Process.wait fork{} + true + rescue NotImplementedError, NoMethodError + false + end + end + else + # assume non windows is posix + true + end + end + end + + # true for linux, false for windows, os x, cygwin + def self.linux? + if (host_os =~ /linux/) + true + else + false + end + end + + def self.freebsd? + if (host_os =~ /freebsd/) + true + else + false + end + end + + def self.iron_ruby? + @iron_ruby ||= begin + if defined?(RUBY_ENGINE) && (RUBY_ENGINE == 'ironruby') + true + else + false + end + end + end + + def self.bits + @bits ||= begin + if host_cpu =~ /_64$/ || RUBY_PLATFORM =~ /x86_64/ + 64 + elsif RUBY_PLATFORM == 'java' && ENV_JAVA['sun.arch.data.model'] # "32" or "64":http://www.ruby-forum.com/topic/202173#880613 + ENV_JAVA['sun.arch.data.model'].to_i + elsif host_cpu == 'i386' + 32 + elsif host_os =~ /32$/ # mingw32, mswin32 + 32 + else # cygwin only...I think + if 1.size == 8 + 64 + else + 32 + end + end + end + end + + + def self.java? + @java ||= begin + if RUBY_PLATFORM =~ /java/ + true + else + false + end + end + end + + def self.ruby_bin + @ruby_exe ||= begin + File::join(config['bindir'], config['ruby_install_name']) + config['EXEEXT'] + end + end + + def self.mac? + @mac = begin + if host_os =~ /darwin/ + true + else + false + end + end + end + + def self.osx? + mac? + end + + def self.x? + mac? + end + + + # amount of memory the current process "is using", in RAM + # (doesn't include any swap memory that it may be using, just that in actual RAM) + # raises 'unknown' on jruby currently + def self.rss_bytes + # attempt to do this in a jruby friendly way + if OS::Underlying.windows? + # MRI, Java, IronRuby, Cygwin + if OS.java? + # no win32ole on 1.5.x, so leave here for compatibility...maybe for awhile :P + require 'java' + mem_bean = java.lang.management.ManagementFactory.getMemoryMXBean + mem_bean.heap_memory_usage.used + mem_bean.non_heap_memory_usage.used + else + wmi = nil + begin + require 'win32ole' + wmi = WIN32OLE.connect("winmgmts://") + rescue LoadError, NoMethodError => e # NoMethod for IronRuby currently [sigh] + raise 'rss unknown for this platform ' + e.to_s + end + processes = wmi.ExecQuery("select * from win32_process where ProcessId = #{Process.pid}") + memory_used = nil + # only allow for one... + for process in processes + raise if memory_used + memory_used = process.WorkingSetSize.to_i + end + memory_used + end + elsif OS.posix? # linux [though I've heard it works in OS X] + `ps -o rss= -p #{Process.pid}`.to_i # in kilobytes + else + raise 'unknown rss for this platform' + end + end + + class Underlying + + def self.bsd? + OS.osx? + end + + def self.windows? + ENV['OS'] == 'Windows_NT' + end + + def self.linux? + OS.host_os =~ /linux/ ? true : false + end + + def self.docker? + system('grep -q docker /proc/self/cgroup') if OS.linux? + end + + end + + def self.cygwin? + @cygwin = begin + if RUBY_PLATFORM =~ /-cygwin/ + true + else + false + end + end + end + + def self.dev_null # File::NULL in 1.9.3+ + @dev_null ||= begin + if OS.windows? + "NUL" + else + "/dev/null" + end + end + end + + # provides easy way to see the relevant config entries + def self.report + relevant_keys = [ + 'arch', + 'host', + 'host_cpu', + 'host_os', + 'host_vendor', + 'target', + 'target_cpu', + 'target_os', + 'target_vendor', + ] + RbConfig::CONFIG.reject {|key, val| !relevant_keys.include? key }.merge({'RUBY_PLATFORM' => RUBY_PLATFORM}).to_yaml + end + + def self.cpu_count + @cpu_count ||= + case RUBY_PLATFORM + when /darwin9/ + `hwprefs cpu_count`.to_i + when /darwin10/ + (hwprefs_available? ? `hwprefs thread_count` : `sysctl -n hw.ncpu`).to_i + when /linux/ + IO.readlines('/proc/cpuinfo').count { |x| x[/^processor/] } + when /freebsd/ + `sysctl -n hw.ncpu`.to_i + else + if RbConfig::CONFIG['host_os'] =~ /darwin/ + (hwprefs_available? ? `hwprefs thread_count` : `sysctl -n hw.ncpu`).to_i + elsif self.windows? + # ENV counts hyper threaded...not good. + # out = ENV['NUMBER_OF_PROCESSORS'].to_i + require 'win32ole' + wmi = WIN32OLE.connect("winmgmts://") + cpu = wmi.ExecQuery("select NumberOfCores from Win32_Processor") # don't count hyper-threaded in this + cpu.to_enum.first.NumberOfCores + else + raise 'unknown platform processor_count' + end + end + end + + def self.ipv4_private + require 'socket' + ip = Socket.ip_address_list.detect(&:ipv4_private?) + ip ? ip.ip? ? ip.ip_unpack[0] : '' : '' + end + + def self.open_file_command + if OS.doze? || OS.cygwin? + "start" + elsif OS.mac? + "open" + else + # linux...what about cygwin? + "xdg-open" + end + end + + def self.app_config_path(name) + if OS.doze? + if ENV['LOCALAPPDATA'] + return File.join(ENV['LOCALAPPDATA'], name) + end + + File.join ENV['USERPROFILE'], 'Local Settings', 'Application Data', name + elsif OS.mac? + File.join ENV['HOME'], 'Library', 'Application Support', name + else + if ENV['XDG_CONFIG_HOME'] + return File.join(ENV['XDG_CONFIG_HOME'], name) + end + + File.join ENV['HOME'], '.config', name + end + end + + def self.parse_os_release + parse_release('/etc/os-release') + end + + def self.parse_lsb_release + parse_release('/etc/lsb-release') + end + + class << self + alias :doze? :windows? # a joke name but I use it and like it :P + alias :jruby? :java? + + # delegators for relevant config values + %w(host host_cpu host_os).each do |method_name| + define_method(method_name) { config[method_name] } + end + + end + + private + + def self.hwprefs_available? + `which hwprefs` != '' + end + + def self.parse_release(file) + if OS.linux? && File.readable?(file) + File.readlines(file).reduce({}) do |output, line| + parsed_line = line.strip.delete(?").split('=') + next if parsed_line.empty? + output.merge(parsed_line[0].to_sym => parsed_line[1]) + end + else + raise "File #{file} doesn't exist or not Linux" + end + end end From c4a3b7e66885ca454180e0c305507793559f9a4c Mon Sep 17 00:00:00 2001 From: Sourav Goswami Date: Sat, 21 Nov 2020 13:32:33 +0530 Subject: [PATCH 4/8] Use File::NULL to detect null file if the target is not Windows --- lib/os.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/os.rb b/lib/os.rb index 80cf135..4694ecb 100644 --- a/lib/os.rb +++ b/lib/os.rb @@ -203,7 +203,7 @@ def self.dev_null # File::NULL in 1.9.3+ if OS.windows? "NUL" else - "/dev/null" + File::NULL end end end From e9b01bb788b7806f75eb6e3498dbe09ce29e48e3 Mon Sep 17 00:00:00 2001 From: Sourav Goswami Date: Sat, 21 Nov 2020 13:43:56 +0530 Subject: [PATCH 5/8] Fix processor count for JRuby and Other platforms --- lib/os.rb | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/lib/os.rb b/lib/os.rb index 4694ecb..8ceaa93 100644 --- a/lib/os.rb +++ b/lib/os.rb @@ -68,11 +68,7 @@ def self.freebsd? def self.iron_ruby? @iron_ruby ||= begin - if defined?(RUBY_ENGINE) && (RUBY_ENGINE == 'ironruby') - true - else - false - end + defined?(RUBY_ENGINE) && (RUBY_ENGINE == 'ironruby') end end @@ -131,7 +127,6 @@ def self.x? mac? end - # amount of memory the current process "is using", in RAM # (doesn't include any swap memory that it may be using, just that in actual RAM) # raises 'unknown' on jruby currently @@ -236,7 +231,10 @@ def self.cpu_count when /freebsd/ `sysctl -n hw.ncpu`.to_i else - if RbConfig::CONFIG['host_os'] =~ /darwin/ + if File.readable?('/proc/cpuinfo') + # JRuby workaround ; should also work on the Android if cpuinfo is available to user + IO.readlines('/proc/cpuinfo').count { |x| x[/^processor/] } + elsif RbConfig::CONFIG['host_os'] =~ /darwin/ (hwprefs_available? ? `hwprefs thread_count` : `sysctl -n hw.ncpu`).to_i elsif self.windows? # ENV counts hyper threaded...not good. @@ -246,7 +244,12 @@ def self.cpu_count cpu = wmi.ExecQuery("select NumberOfCores from Win32_Processor") # don't count hyper-threaded in this cpu.to_enum.first.NumberOfCores else - raise 'unknown platform processor_count' + begin + require 'etc' + Etc.nprocessors + rescue Exception + raise 'unknown platform processor_count' + end end end end From a05c479b15fc704767e88b5dc2fa80edd5a94bc4 Mon Sep 17 00:00:00 2001 From: Sourav Goswami Date: Sat, 21 Nov 2020 15:37:15 +0530 Subject: [PATCH 6/8] Bugs fixed if line is empty --- Gemfile.lock | 4 ++-- lib/os.rb | 3 +-- p.rb | 14 ++++++++++++++ 3 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 p.rb diff --git a/Gemfile.lock b/Gemfile.lock index d64ff4e..2fa4fa5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - os (1.0.1) + os (1.1.1) GEM remote: http://rubygems.org/ @@ -27,7 +27,7 @@ PLATFORMS DEPENDENCIES os! rake (~> 0.8) - rspec (~> 2.5.0) + rspec (>= 2.0) test-unit (~> 3) BUNDLED WITH diff --git a/lib/os.rb b/lib/os.rb index 8ceaa93..ebd6c87 100644 --- a/lib/os.rb +++ b/lib/os.rb @@ -318,8 +318,7 @@ def self.parse_release(file) if OS.linux? && File.readable?(file) File.readlines(file).reduce({}) do |output, line| parsed_line = line.strip.delete(?").split('=') - next if parsed_line.empty? - output.merge(parsed_line[0].to_sym => parsed_line[1]) + parsed_line.empty? ? output : output.merge(parsed_line[0].to_sym => parsed_line[1]) end else raise "File #{file} doesn't exist or not Linux" diff --git a/p.rb b/p.rb new file mode 100644 index 0000000..e2e5496 --- /dev/null +++ b/p.rb @@ -0,0 +1,14 @@ +require_relative File.join(__dir__, 'lib', 'os') + +puts %i( + windows? mac? linux? + java? + cpu_count open_file_command + parse_os_release + parse_lsb_release + ipv4_private + rss_bytes + dev_null + iron_ruby? + +).map { |x| "#{x} => #{OS.send(x)}" } From aabe5c62607d4506451e256e1059ca5ca172c590 Mon Sep 17 00:00:00 2001 From: Sourav Goswami Date: Sat, 21 Nov 2020 15:38:45 +0530 Subject: [PATCH 7/8] Clean up --- p.rb | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 p.rb diff --git a/p.rb b/p.rb deleted file mode 100644 index e2e5496..0000000 --- a/p.rb +++ /dev/null @@ -1,14 +0,0 @@ -require_relative File.join(__dir__, 'lib', 'os') - -puts %i( - windows? mac? linux? - java? - cpu_count open_file_command - parse_os_release - parse_lsb_release - ipv4_private - rss_bytes - dev_null - iron_ruby? - -).map { |x| "#{x} => #{OS.send(x)}" } From e2874e7bc97e0781e9af87e0aa84e2f8eb4da477 Mon Sep 17 00:00:00 2001 From: Sourav Goswami Date: Sat, 21 Nov 2020 15:45:10 +0530 Subject: [PATCH 8/8] Bugs fixed when os_release is empty --- lib/os.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/os.rb b/lib/os.rb index 8ceaa93..ebd6c87 100644 --- a/lib/os.rb +++ b/lib/os.rb @@ -318,8 +318,7 @@ def self.parse_release(file) if OS.linux? && File.readable?(file) File.readlines(file).reduce({}) do |output, line| parsed_line = line.strip.delete(?").split('=') - next if parsed_line.empty? - output.merge(parsed_line[0].to_sym => parsed_line[1]) + parsed_line.empty? ? output : output.merge(parsed_line[0].to_sym => parsed_line[1]) end else raise "File #{file} doesn't exist or not Linux"