class PosixPsutil::Disks

Public Class Methods

disk_io_counters(perdisk=true) click to toggle source

Return disk I/O statistics for every disk installed on the system as an Array of <OpenStruct read_count, write_count, read_bytes, write_bytes, read_time, write_time>

# File linux/system.rb, line 318
def self.disk_io_counters(perdisk=true)
  # get disks list
  partitions = []
  lines = IO.readlines('/proc/partitions')[2..-1]
  # reverse lines so sda will be below sda1
  lines.reverse_each do |line|
    name = line.split(' ')[3]
    if name[-1] === /\d/
      # we're dealing with a partition (e.g. 'sda1'); 'sda' will
      # also be around but we want to omit it
      partitions.push(name)
    elsif partitions.empty? || !partitions[-1].start_with?(name)
      # we're dealing with a disk entity for which no
      # partitions have been defined (e.g. 'sda' but
      # 'sda1' was not around), see:
      # https://github.com/giampaolo/psutil/issues/338
      partitions.push(name)
    end
  end

  ret = {}

  # man iostat states that sectors are equivalent with blocks and
  # have a size of 512 bytes since 2.4 kernels. This value is
  # needed to calculate the amount of disk I/O in bytes.
  sector_size = 512
  # get disks stats
  IO.readlines('/proc/diskstats').each do |line|
    fields = line.split()
    if partitions.include?(fields[2])
      # go to http://www.mjmwired.net/kernel/Documentation/iostats.txt
      # and see what these fields mean
      if fields.length
        _, _, name, reads, _, rbytes, rtime, writes, _, wbytes, wtime = 
          fields[0..10]
      else
        # < kernel 2.6.25
        _, _, name, reads, rbytes, writes, wbytes = fields
        rtime, wtime = 0, 0
      end

      # fill with the data
      disk = OpenStruct.new
      disk.read_bytes = rbytes.to_i * sector_size
      disk.write_bytes = wbytes.to_i * sector_size
      disk.read_count = reads.to_i
      disk.write_count = writes.to_i
      disk.read_time = rtime.to_i
      disk.write_time = wtime.to_i
      ret[name] = disk
    end # end if name in partitions
  end # end read /proc/diskstats

  # handle ret
  if perdisk
    return ret
  else
    total = OpenStruct.new(read_bytes: 0, write_bytes: 0, read_count: 0, 
                           write_count: 0, read_time: 0, write_time: 0)
    ret.each_value do |disk|
      total.read_bytes += disk.read_bytes
      total.write_bytes += disk.write_bytes
      total.read_count += disk.read_count
      total.write_count += disk.write_count
      total.read_time += disk.read_time
      total.write_time += disk.write_time
    end

    return total
  end
end
disk_partitions() click to toggle source

Return mounted disk partitions as an Array of <OpenStruct device, mountpoint, fstype, opts>

# File linux/system.rb, line 261
def self.disk_partitions()
  phydevs = []
  # get physical filesystems
  IO.readlines('/proc/filesystems').each do |line|
    phydevs.push(line.strip()) unless line.start_with?('nodev')
  end

  ret = []
  # there will be some devices with /dev/disk/by-*, they are symbol links to physical devices
  IO.readlines('/proc/self/mounts').each do |line|
    line = line.split(' ')
    # omit virtual filesystems
    if phydevs.include?(line[2])
      partition = OpenStruct.new
      partition.device = line[0]
      partition.mountpoint = line[1]
      partition.fstype = line[2]
      partition.opts = line[3]
      ret.push(partition)
    end
  end
  ret
end
disk_usage(disk) click to toggle source

Return disk usage associated with path, representing in <OpenStruct free, total, used, percent>. WARNING: this method show the usage of a disk instead of a given path!

# File linux/system.rb, line 288
def self.disk_usage(disk)
  usage = OpenStruct.new
  begin
    frsize = FFI::MemoryPointer.new(:ulong, 1)
    blocks = FFI::MemoryPointer.new(:ulong, 1)
    bavail = FFI::MemoryPointer.new(:ulong, 1)
    bfree = FFI::MemoryPointer.new(:ulong, 1)
    status = LibPosixPsutil::disk_usage(disk, frsize, blocks, bavail, bfree)
    raise SystemCallError.new("in disk_usage", status) if status != 0
    frsize = frsize.read_ulong
    blocks = blocks.read_ulong
    bavail = bavail.read_ulong
    bfree = bfree.read_ulong
    usage.free = bavail * frsize
    usage.total = blocks * frsize
    usage.used = (blocks - bfree) * frsize
    # NB: the percentage is -5% than what shown by df due to
    # reserved blocks that we are currently not considering:
    # http://goo.gl/sWGbH
    usage.percent = COMMON::usage_percent(usage.used, usage.total, 1)
  rescue Errno::ENOENT
    msg = "Given Argument #{disk} is not a disk name"
    throw ArgumentError.new(msg) if usage.total.nil?
  end
  usage
end