Module: Sys

Defined in:
lib/epitools/sys/os.rb,
lib/epitools/sys/ps.rb,
lib/epitools/sys/mem.rb,
lib/epitools/sys/net.rb,
lib/epitools/sys/misc.rb,
lib/epitools/sys/mounts.rb

Defined Under Namespace

Classes: Mount, ProcessInfo, ProcessNotFound

Constant Summary collapse

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 =

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.bsd?Boolean

Is this BSD?

Returns:

  • (Boolean)


61
62
63
# File 'lib/epitools/sys/os.rb', line 61

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.)



81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/epitools/sys/os.rb', line 81

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?

Returns:

  • (Boolean)


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

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

.hostname_linuxObject



7
8
9
# File 'lib/epitools/sys/net.rb', line 7

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

.hostname_macObject



11
12
13
# File 'lib/epitools/sys/net.rb', line 11

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

.hostname_windowsObject

Raises:

  • (NotImplementedError)


15
16
17
# File 'lib/epitools/sys/net.rb', line 15

def self.hostname_windows
  raise NotImplementedError
end

.interfaces_bsdObject

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

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



28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/epitools/sys/net.rb', line 28

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

Darwin: Do whatever BSD does



45
46
47
# File 'lib/epitools/sys/net.rb', line 45

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”



54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/epitools/sys/net.rb', line 54

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.



71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/epitools/sys/net.rb', line 71

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?

Returns:

  • (Boolean)


35
36
37
# File 'lib/epitools/sys/os.rb', line 35

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

.mac?Boolean

Is this a Mac? (aka. Darwin?)

Returns:

  • (Boolean)


56
# File 'lib/epitools/sys/os.rb', line 56

def self.mac?; darwin?; end

.memstat_darwinObject



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

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



7
8
9
10
11
12
13
14
15
16
# File 'lib/epitools/sys/mem.rb', line 7

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

.mountsObject

Get an array of mounted filesystems (as fancy objects)



6
7
8
9
10
11
12
# File 'lib/epitools/sys/mounts.rb', line 6

def self.mounts
  if linux?
    IO.popen(["findmnt", "--raw"]) { |io| io.drop(1).map { |line| Mount.new line } }
  else
    raise NotImplementedError.new("I dunno, how do you find mounts on #{os}?")
  end
end

.osObject

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



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/epitools/sys/os.rb', line 6

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.)



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/epitools/sys/ps.rb', line 9

def self.ps(*pids)
  raise "that's too many pids!" if pids.size > 999_999

  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

.temperaturesObject


Raises:

  • (NotImplementedError)


47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/epitools/sys/misc.rb', line 47

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 NotImplementedError.new("Sorry")
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.



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/epitools/sys/misc.rb', line 11

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




38
39
40
41
42
43
44
# File 'lib/epitools/sys/ps.rb', line 38

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?

Returns:

  • (Boolean)


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

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

Instance Method Details

#browser_open_darwin(url) ⇒ Object

Darwin: Open the webpage in a new chrome tab.



41
42
43
# File 'lib/epitools/sys/misc.rb', line 41

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 “xdg-open”).



34
35
36
# File 'lib/epitools/sys/misc.rb', line 34

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