Class: PosixPsutil::Disks

Inherits:
Object
  • Object
show all
Defined in:
lib/posixpsutil/linux/system.rb

Class Method Summary collapse

Class Method Details

.disk_io_counters(perdisk = true) ⇒ Object

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>



318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
# File 'lib/posixpsutil/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_partitionsObject

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



261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
# File 'lib/posixpsutil/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) ⇒ Object

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!



288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
# File 'lib/posixpsutil/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