Module: BBLib::OS

Defined in:
lib/os/bbos.rb,
lib/os/bbsys.rb

Class Method Summary collapse

Class Method Details

.cpu_free_pObject



32
33
34
# File 'lib/os/bbsys.rb', line 32

def self.cpu_free_p
  100 - cpu_used
end

.cpu_usagesObject



7
8
9
10
11
12
13
14
15
16
17
# File 'lib/os/bbsys.rb', line 7

def self.cpu_usages
  if windows?
    {
      total: `wmic cpu get loadpercentage /format:value`.extract_numbers.first.to_f
    }
  elsif linux? || mac?
    system_stats[:cpu]
  else
    nil
  end
end

.cpu_used_pObject



28
29
30
# File 'lib/os/bbsys.rb', line 28

def self.cpu_used_p
  cpu_usages[:total]
end

.filesystemsObject



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/os/bbsys.rb', line 159

def self.filesystems
  if windows?
    types = {
      0 => 'Unknown',
      1 => 'No Root Directory',
      2 => 'Removable Disk',
      3 => 'Local Disk',
      4 => 'Network Drive',
      5 => 'Compact Disc',
      6 => 'RAM Disk'
    }
    parse_wmic('wmic logicaldisk get name,description,filesystem,freespace,size,volumename,volumeserialnumber,providername,drivetype')
      .map do |v|
        v.hpath_move(
          'freespace'          => 'free',
          'providername'       => 'provider',
          'volumename'         => 'volume_name',
          'volumeserialnumber' => 'serial_number',
          'filesystem'         => 'filesystem_type',
          'name'               => 'disk'
        )
        dt = v.delete(:drivetype).to_i
        v[:type] = types[dt]
        if (2..4) === dt
          v[:free]   = v[:free].to_i
          v[:size]   = v[:size].to_i
          v[:used]   = v[:size] - v[:free]
          v[:free_p] = (v[:free] / v[:size].to_f) * 100
          v[:used_p] = (v[:used] / v[:size].to_f) * 100
        end
        v
      end
  else
    `df -aTB 1`
      .split("\n")[1..-1]
      .map{ |l| l.split(/\s{2,}|(?<=\d)\s|(?<=%)\s|(?<=\-)\s|(?<=\w)\s+(?=\w+\s+\d)/)}
      .map do |i|
        {
          filesystem: i[0],
          type:       i[1],
          size:       i[2].to_i,
          used:       i[3].to_i,
          available:  i[4].to_i,
          used_p:     i[5].extract_integers.first.to_f,
          mount:      i[6],
        }
      end
  end
end

.linux?Boolean

Returns:

  • (Boolean)


18
19
20
# File 'lib/os/bbos.rb', line 18

def self.linux?
  !windows? && !mac?
end

.mac?Boolean

Returns:

  • (Boolean)


26
27
28
29
# File 'lib/os/bbos.rb', line 26

def self.mac?
  builds = ['darwin']
  !(/#{builds.join('|')}/i =~ RUBY_PLATFORM).nil?
end

.mem_freeObject



54
55
56
57
58
59
60
61
62
# File 'lib/os/bbsys.rb', line 54

def self.mem_free
  if windows?
    `wmic os get freephysicalmemory /format:value`.extract_numbers.first
  elsif linux?
    system_stats.hpath('memory.free')
  else
    nil
  end
end

.mem_free_pObject



64
65
66
# File 'lib/os/bbsys.rb', line 64

def self.mem_free_p
  (mem_free.to_f / mem_total.to_f) * 100.0
end

.mem_totalObject



36
37
38
39
40
41
42
43
44
# File 'lib/os/bbsys.rb', line 36

def self.mem_total
  if windows?
    `wmic computersystem get TotalPhysicalMemory`.extract_numbers.first / 1024.0
  elsif linux?
    system_stats.hpath('memory.total')
  else
    nil
  end
end

.mem_usedObject



46
47
48
# File 'lib/os/bbsys.rb', line 46

def self.mem_used
  mem_total.to_f - mem_free.to_f
end

.mem_used_pObject



50
51
52
# File 'lib/os/bbsys.rb', line 50

def self.mem_used_p
  (mem_used.to_f / mem_total.to_f) * 100.0
end

.osObject



7
8
9
10
11
# File 'lib/os/bbos.rb', line 7

def self.os
  return :windows if windows?
  return :mac if mac?
  return :linux if linux?
end

.os_infoObject



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/os/bbos.rb', line 31

def self.os_info
  if windows?
    data = `wmic os get manufacturer,name,organization,osarchitecture,version /format:list`
    data = data.split("\n").reject{ |r| r.strip == '' }.map do |m|
      spl = m.split('=')
      [spl.first.to_clean_sym.downcase, spl[1..-1].join('=')]
    end.to_h
    data[:name] = data[:name].split('|').first
    data[:osarchitecture] = data[:osarchitecture].extract_integers.first
    data.hpath_move( 'osarchitecture' => 'bits' )
    data[:host] = `hostname`.strip
    data[:os] = os
    data
  else
    release = {}
    begin
      # First attempt to get release info uses lsb_release

      release = `lsb_release -a`.split("\n").map do |l|
        spl = l.split(':')
        [
          spl.first.downcase.to_clean_sym,
          spl[1..-1].join(':').strip
        ]
      end.to_h
      release.hpath_move('description' => 'name', 'release' => 'name', 'distributor_id' => 'manufacturer')
    rescue
      # Try finding the release file and parsing it instead of lsb_release

      begin
        release = `cat /etc/*release`
          .split("\n")
          .reject{ |l| !(l.include?(':') || l.include?('=')) }
          .map{|l| l.msplit('=',':') }
          .map{ |a| [a.first.downcase.to_clean_sym, a[1..-1].join(':').uncapsulate] }
          .to_h
      rescue
        # Both attempts failed

      end
    end
    {
      release: `uname -r`.strip,
      bits:    `uname -r` =~ /x86_64/i ? 64 : 32,
      host:    `uname -n`.strip,
      os:      os
    }.merge(release)
  end
end

.parse_wmic(cmd) ⇒ Object



81
82
83
84
85
86
87
# File 'lib/os/bbos.rb', line 81

def self.parse_wmic cmd
  `#{cmd} /format:list`
    .split("\n\n\n").reject(&:empty?)
    .map{ |l| l.split("\n\n")
      .map{ |l| spl = l.split('='); [spl.first.strip.downcase.to_clean_sym, spl[1..-1].join('=').strip ] }.to_h
    }.reject(&:empty?)
end

.processesObject



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/os/bbsys.rb', line 121

def self.processes
  if windows?
    tasks = `tasklist /v`
    cpu = `wmic path win32_perfformatteddata_perfproc_process get PercentProcessorTime,percentusertime,IDProcess /format:list`
    cpu = cpu.split("\n\n\n\n").reject(&:empty?)
          .map{ |l| l.scan(/\d+/).map(&:to_i)}
          .map{ |n|[ n[0], {cpu: n[1], user: n[2] }]}.to_h
    lines = tasks.split("\n")[3..-1].map{ |l| l.split(/\s{2,}/) }
    mem = mem_total
    cmds = `wmic process get processid,commandline /format:csv`.split("\n")[1..-1].reject{ |r| r.strip  == ''}.map{ |l| l.split(',')[1..-1] }.map{ |l| [l.last.to_i, l[0..-2].join(',')]}.to_h
    lines.map do |l|
      pid = l[1].extract_numbers.first
      {
        name: l[0],
        pid:  pid,
        user: l[4],
        mem:  (((l[3].gsub(',', '').extract_numbers.first / mem_total) * 100) rescue nil),
        cpu:  (cpu[pid][:cpu] rescue nil),
        cmd:  cmds[pid]
      }
    end
  else
    t = `ps -e -o comm,pid,ruser,%cpu,%mem,cmd`
    lines = t.split("\n")[1..-1].map{ |l| l.split(/\s+/) }
    lines.map{ |l| l.size == 6 ? l : [l[0], l[1], l[2], l[3], l[4], l[5..-1].join(' ')] }
    lines.map do |l|
      {
        name: l[0],
        pid:  l[1].to_i,
        user: l[2],
        cpu:  l[3].to_f,
        mem:  l[4].to_f,
        cmd:  l[5]
      }
    end
  end
end

.root_volume_labelsObject

Windows only method to get the volume labels of disk drives



232
233
234
235
# File 'lib/os/bbsys.rb', line 232

def self.root_volume_labels
  return nil unless BBLib.windows?
  `wmic logicaldisk get caption,volumename`.split("\n")[1..-1].map{ |m| [m.split("  ").first.to_s.strip, m.split("  ")[1..-1].to_a.join(' ').strip] }.reject{ |o,t| o == '' }.to_h
end

.root_volumesObject

A mostly platform agnostic call to get root volumes



211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'lib/os/bbsys.rb', line 211

def self.root_volumes
  if BBLib.windows?
    begin # For windows

      `wmic logicaldisk get name`.split("\n").map{ |m| m.strip }[1..-1].reject{ |r| r == '' }
    rescue
      begin # Windows attempt 2

        `fsutil fsinfo drives`.scan(/(?<=\s)\w\:/)
      rescue
        nil
      end
    end
  else
    begin
      `ls /`.split("\n").map{ |m| m.strip }.reject{ |r| r == '' }
    rescue # All attempts failed

      nil
    end
  end
end

.system_statsObject



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/os/bbsys.rb', line 68

def self.system_stats
  if windows?
    memfree  = mem_free
    memtotal = mem_total
    memused  = memtotal - memfree
    {
      cpu: cpu_usages,
      memory: {
        free:   memfree,
        used:   memused,
        total:  memtotal,
        free_p: (memfree / memtotal.to_f) * 100,
        used_p: (memused / memtotal.to_f) * 100
      },
      uptime: uptime
    }
  else
    stats = `top -b -n2 -d 0.1`.split("\n")
    cpu   = stats.find_all{|l| l =~ /\A\%?Cpu\(s\)/i }.last.extract_numbers
    loads = stats.find_all{|l| l =~ / load average\: /i }.last.scan(/load average:.*/i).first.extract_numbers
    mem   = stats.find_all{|l| l =~ /KiB Mem|Mem\:/i }.last.extract_numbers
    time  = `cat /proc/uptime`.extract_numbers
    {
      cpu: {
        user:                cpu[0],
        system:              cpu[1],
        nice:                cpu[2],
        total:               cpu[0..2].inject(0){ |sum, v| sum += v.to_f },
        idle:                cpu[3],
        wait:                cpu[4],
        hardware_interrupts: cpu[5],
        software_interrupts: cpu[6],
        hypervisor:          cpu[7]
      },
      uptime: time[0],
      uptime_idle: time[1],
      memory: {
        free:   mem[1],
        used:   mem[2],
        total:  mem[0],
        cache:  mem[3],
        free_p: (mem[1] / mem[0].to_f) * 100,
        used_p: (mem[2] / mem[0].to_f) * 100
      },
      load_average: {
        1 => loads[0],
        5 => loads[1],
        15 => loads[2]
      }
    }
  end
end

.unix?Boolean

Returns:

  • (Boolean)


22
23
24
# File 'lib/os/bbos.rb', line 22

def self.unix?
  !windows?
end

.uptimeObject



19
20
21
22
23
24
25
26
# File 'lib/os/bbsys.rb', line 19

def self.uptime
  if windows?
    uptime = `net statistics server`.split("\n").find{|l| l.start_with?('Statistics since ')}.split(/since /i).last.strip
    Time.now - Time.strptime(uptime, '%m/%d/%Y %l:%M:%S %p')
  else
    `cat /proc/uptime`.extract_numbers.first
  end
end

.windows?Boolean

Returns:

  • (Boolean)


13
14
15
16
# File 'lib/os/bbos.rb', line 13

def self.windows?
  builds = ['mingw', 'mswin', 'cygwin', 'bccwin']
  !(/#{builds.join('|')}/i =~ RUBY_PLATFORM).nil?
end