Module: Sys

Defined in:
lib/epitools/sys.rb

Overview

Cross-platform operating system functions. Includes: process listing, platform detection, etc.

Defined Under Namespace

Classes: ProcessInfo, ProcessNotFound

Constant Summary

PS_FIELD_TABLE =

[
  [:pid,    :to_i],
  [:ppid,   :to_i],
  [:pcpu,   :to_f],
  [:pmem,   :to_f],
  [:stat,   :to_s],
  [:rss,    :to_i],
  [:vsz,    :to_i],
  [:user,   :to_s],
  [:majflt, :to_i],
  [:minflt, :to_i],
  [:command,:to_s],
]
PS_FIELDS =
PS_FIELD_TABLE.map { |name, func| name }
PS_FIELD_TRANSFORMS =
Hash[ *PS_FIELD_TABLE.flatten ]

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.bsd?Boolean

Is this BSD?



69
70
71
# File 'lib/epitools/sys.rb', line 69

def self.bsd?
  os == "BSD" or os == "Darwin"
end

.cross_platform_method(name) ⇒ Object

A metaprogramming helper that allows you to write platform-specific methods which the user can call with one name. Here's how to use it:

Define these methods:

reboot_linux, reboot_darwin, reboot_windows

Call the magic method:

cross_platform_method(:reboot)

Now the user can execute “reboot” on any platform!

(Note: If you didn't create a method for a specific platform, then you'll get NoMethodError exception when the “reboot” method is called on that platform.)



325
326
327
328
329
330
331
332
333
334
335
336
# File 'lib/epitools/sys.rb', line 325

def self.cross_platform_method(name)
  platform_method_name = "#{name}_#{os.downcase}"
  metaclass.instance_eval do
    define_method(name) do |*args|
      begin
        self.send(platform_method_name, *args)
      rescue NoMethodError
        raise NotImplementedError.new("#{name} is not yet supported on #{os}.")
      end
    end
  end
end

.darwin?Boolean

Is this Darwin?



57
58
59
# File 'lib/epitools/sys.rb', line 57

def self.darwin?
  os == "Darwin"
end

.hostname_linuxObject



342
343
344
# File 'lib/epitools/sys.rb', line 342

def self.hostname_linux
  `uname -n`.strip
end

.hostname_macObject



346
347
348
# File 'lib/epitools/sys.rb', line 346

def self.hostname_mac
  `uname -n`.strip.gsub(/\.local$/, '')
end

.hostname_windowsObject

Raises:

  • (NotImplementedError)


350
351
352
# File 'lib/epitools/sys.rb', line 350

def self.hostname_windows
  raise NotImplementedError
end

.interfaces_bsdObject

Darwin: Return a hash of (device, IP address) pairs.

eg: “en0”=>“192“en0”=>“192.168“en0”=>“192.168.1“en0”=>“192.168.1.101”



363
364
365
366
367
368
369
370
371
372
373
374
375
# File 'lib/epitools/sys.rb', line 363

def self.interfaces_bsd
  sections = `ifconfig`.split(/^(?=[^\t])/)
  sections_with_relevant_ip = sections.select {|i| i =~ /inet/ }

  device_ips = {}
  sections_with_relevant_ip.each do |section|
    device  = section[/[^:]+/]
    ip      = section[/inet ([^ ]+)/, 1]
    device_ips[device] = ip
  end

  device_ips
end

.interfaces_darwinObject



377
# File 'lib/epitools/sys.rb', line 377

def self.interfaces_darwin; interfaces_bsd; end

.interfaces_linuxObject

Linux: Return a hash of (device, IP address) pairs.

eg: “eth0”=>“192“eth0”=>“192.168“eth0”=>“192.168.1“eth0”=>“192.168.1.101”



384
385
386
387
388
389
390
391
392
393
394
395
396
# File 'lib/epitools/sys.rb', line 384

def self.interfaces_linux
  sections = `/sbin/ifconfig`.split(/^(?=Link encap:Ethernet)/)
  sections_with_relevant_ip = sections.select {|i| i =~ /inet/ }

  device_ips = {}
  sections_with_relevant_ip.each do |section|
    device  = section[/([\w\d]+)\s+Link encap:Ethernet/, 1]
    ip      = section[/inet addr:([^\s]+)/, 1]
    device_ips[device] = ip
  end

  device_ips
end

.interfaces_windowsObject

Windows: Return a hash of (device name, IP address) pairs.



401
402
403
404
405
406
407
408
409
410
411
412
413
# File 'lib/epitools/sys.rb', line 401

def self.interfaces_windows
  result = {}
  `ipconfig`.split_before(/^\w.+:/).each do |chunk|
    chunk.grep(/^Ethernet adapter (.+):\s*$/) do
      name = $1
      chunk.grep(/IPv[46] Address[\.\ ]+: (.+)$/) do
        address = $1.strip
        result[name] = address
      end
    end
  end
  result
end

.linux?Boolean

Is this Linux?



43
44
45
# File 'lib/epitools/sys.rb', line 43

def self.linux?
  os == "Linux"
end

.mac?Boolean

Is this a Mac? (aka. Darwin?)



64
# File 'lib/epitools/sys.rb', line 64

def self.mac?; darwin?; end

.memstat_darwinObject



448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
# File 'lib/epitools/sys.rb', line 448

def self.memstat_darwin
  #$ vm_stat
  #Mach Virtual Memory Statistics: (page size of 4096 bytes)
  #Pages free:                         198367.
  #Pages active:                       109319.
  #Pages inactive:                      61946.
  #Pages speculative:                   18674.
  #Pages wired down:                    70207.
  #"Translation faults":            158788687.
  #Pages copy-on-write:              17206973.
  #Pages zero filled:                54584525.
  #Pages reactivated:                    8768.
  #Pageins:                            176076.
  #Pageouts:                             3757.
  #Object cache: 16 hits of 255782 lookups (0% hit rate)

  #$ iostat
  raise "Not implemented"    
end

.memstat_linuxObject



437
438
439
440
441
442
443
444
445
446
# File 'lib/epitools/sys.rb', line 437

def self.memstat_linux
  #$ free
  #             total       used       free     shared    buffers     cached
  #Mem:       4124380    3388548     735832          0     561888     968004
  #-/+ buffers/cache:    1858656    2265724
  #Swap:      2104504     166724    1937780
  
  #$ vmstat
  raise "Not implemented"    
end

.osObject

Return the current operating system: Darwin, Linux, or Windows.



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/epitools/sys.rb', line 14

def self.os
  return @os if @os

  require 'rbconfig'
  if defined? RbConfig
    host_os = RbConfig::CONFIG['host_os']
  else
    host_os = Config::CONFIG['host_os']
  end
  
  case host_os
    when /darwin/
      @os = "Darwin"
    when /bsd/
      @os = "BSD"
    when /linux/
      @os = "Linux"
    when /mingw|mswin|cygwin/
      @os = 'Windows'
  else
    #raise "Unknown OS: #{host_os.inspect}"
  end

  @os
end

.ps(*pids) ⇒ Object

List all (or specified) processes, and return ProcessInfo objects. (Takes an optional list of pids as arguments.)



251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# File 'lib/epitools/sys.rb', line 251

def self.ps(*pids)
  #return @@cache if @@cache

  options = PS_FIELDS.join(',')
  
  pids = pids.map(&:to_i)
  
  if pids.any?
    command = "ps -p #{pids.join(',')} -o #{options}"
  else
    command = "ps awx -o #{options}"
  end

  lines = `#{command}`.lines.to_a        

  lines[1..-1].map do |line|
    fields = line.split
    if fields.size > PS_FIELDS.size
      fields = fields[0..PS_FIELDS.size-2] + [fields[PS_FIELDS.size-1..-1].join(" ")] 
    end
    
    fields = PS_FIELDS.zip(fields).map { |name, value| value.send(PS_FIELD_TRANSFORMS[name]) }
    
    ProcessInfo.new(*fields)
  end
end

.refreshObject




280
281
282
# File 'lib/epitools/sys.rb', line 280

def self.refresh
  @@cache = nil
end

.temperaturesObject




470
471
472
473
474
475
476
477
478
479
480
481
# File 'lib/epitools/sys.rb', line 470

def self.temperatures
  #/Applications/Utilities/TemperatureMonitor.app/Contents/MacOS/tempmonitor -a -l
  #CPU Core 1: 28 C
  #CPU Core 2: 28 C
  #SMART Disk Hitachi HTS543216L9SA02 (090831FBE200VCGH3D5F): 40 C
  #SMC CPU A DIODE: 41 C
  #SMC CPU A HEAT SINK: 42 C
  #SMC DRIVE BAY 1: 41 C
  #SMC NORTHBRIDGE POS 1: 46 C
  #SMC WLAN CARD: 45 C
  raise "Not implemented"    
end

.trap(*args, &block) ⇒ Object

Trap signals!

usage: trap(“EXIT”, “HUP”, “ETC”, :ignore=>) { |signal| puts “Got #signal!” } (Execute Signal.list to see what's available.)

No paramters defaults to all signals except VTALRM, CHLD, CLD, and EXIT.



292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'lib/epitools/sys.rb', line 292

def self.trap(*args, &block)
  options = if args.last.is_a?(Hash) then args.pop else Hash.new end
  args = [args].flatten
  signals = if args.any? then args else Signal.list.keys end

  ignore = %w[ VTALRM CHLD CLD EXIT ] unless ignore = options[:ignore]
  ignore = [ignore] unless ignore.is_a? Array

  signals = signals - ignore

  signals.each do |signal|
    p [:sig, signal]
    Signal.trap(signal) { yield signal }
  end
end

.treeObject




239
240
241
242
243
244
245
# File 'lib/epitools/sys.rb', line 239

def self.tree
  tree = Sys.ps.group_by(&:ppid)
  Hash[tree.map do |ppid, children|
    kvs = children.map { |child| [child.pid, tree.delete(child.pid)] }
    [ppid, Hash[kvs]]
  end]
end

.windows?Boolean

Is this Windows?



50
51
52
# File 'lib/epitools/sys.rb', line 50

def self.windows?
  os == "Windows"
end

Instance Method Details

#browser_open_darwin(url) ⇒ Object

Darwin: Open the webpage in a new chrome tab.



429
430
431
# File 'lib/epitools/sys.rb', line 429

def browser_open_darwin(url)
  system("open", "-a", "chrome", url)
end

#browser_open_linux(url) ⇒ Object

Linux: Open an URL in the default browser (using “gnome-open”).



422
423
424
# File 'lib/epitools/sys.rb', line 422

def browser_open_linux(url)
  system("gnome-open", url)
end