Loading...

How to use LinuxStat Rubygem
Sourav Goswami 24 November, 2020 | 04:52:58 UTC (+0000)
LinuxStat is a Linux status reporting gem. Which is really handy when you want to know the state of a linux system for which you are developing a software.
For example, your script can be very heavy, so you need to check the available memory before running the script, this is simple, and you can do that yourself by reading /proc/meminfo and /proc/swaps for sure, but LinuxStat::Memory will let you do that very easily. LinuxStat reads some files that are available to users. So it can work without any root privilege. Stuff like checking CPU usage can be a bit more time consuming though, you need to write a script to do some calculation to do that. But with LinuxStat::CPU, it's very trivial. LinuxStat can do these things pretty efficiently. It could save you a lot of time if you ever need to work with such stuff.

Installation

Installing the gem is very simple. It doesn't require you root permission. But you do need to have GCC, make and ruby.h. On Arch, you can install these two packages:
		pacman -S gcc make
	
On debian however, you need these 3 packages:
		apt install gcc make ruby-dev
	
ruby-dev provides the ruby.h header. You don't have to thing about anything else. Installing for the current user:
		gem install linux_stat --user
	
For root installation:
		gem install linux_stat
	
You might prefer seeing the source code for this gem. Which can be found here. It's also conveniently under open-source MIT licence, and it's free to redistribute as you like.

Usage

Using the gem is quite simple, too... For example, if you need to check the available memory in the current system:
	irb
		irb(main):001:0> require 'linux_stat'
		=> true
		irb(main):002:0> LinuxStat::Memory.available
		=> 327820
		irb(main):003:0> LinuxStat::Memory.percent_available
		=> 8.52
		irb(main):004:0> LinuxStat::Memory.used
		=> 3509708
		irb(main):005:0> LinuxStat::Memory.percent_used
		=> 91.49
		LinuxStat::Memory.total
		=> 3836264
	
Checking the CPU usage is easy peasy! I have a 4 thread CPU:
		irb
		irb(main):001:0> require 'linux_stat'
		=> true
		irb(main):002:0> LinuxStat::CPU.usages
		=> {0=>3.33, 1=>0.0, 2=>12.5, 3=>0.0, 4=>12.5}
		irb(main):003:0> LinuxStat::CPU.count
		=> 4
		irb(main):004:0> LinuxStat::CPU.model
		=> "Intel(R) Core(TM) i3-6006U CPU @ 2.00GHz"
	
But hold on a moment! LinuxStat::CPU.usages() returns 5 values you might wonder. The reason being the first one is aggregated CPU usage reported by the Linux kernel. In most cases, you don't need the per thread usage but the total CPU usage... In that case, you can do:
		irb
		irb(main):001:0> require 'linux_stat'
		=> true
		irb(main):002:0> LinuxStat::CPU.usage
		=> 3.33
	

All Methods and Constants

Apart from CPU and Memory LinuxStat has other methods too! Just look at the constants:
		irb
		irb(main):001:0> require 'linux_stat'
		=> true
		irb(main):002:0> LinuxStat.constants.sort
		[:BIOS, :Battery, :CPU, :Kernel, :Memory, :Net, :OS, :Process, :StatUnavailable, :Swap, :VERSION]
	
So if you run all the methods... On my laptop, at the moment it looks like...:

LinuxStat::BIOS

	LinuxStat::BIOS.date
	=> "04/10/2017"

	LinuxStat::BIOS.model
	=> "Inspiron 5567"

	LinuxStat::BIOS.vendor
	=> "Dell Inc."

	LinuxStat::BIOS.version
	=> "1.1.2"

	

LinuxStat::Battery

	LinuxStat::Battery.charge
	=> 100.0

	LinuxStat::Battery.charging?
	=> true

	LinuxStat::Battery.discharging?
	=> false

	LinuxStat::Battery.full?
	=> true

	LinuxStat::Battery.manufacturer
	=> "Samsung SDI"

	LinuxStat::Battery.model
	=> "DELL CYMGM77"

	LinuxStat::Battery.present?
	=> true

	LinuxStat::Battery.stat
	=> {:model=>"DELL CYMGM77", :manufacturer=>"Samsung SDI", :technology=>"Li-ion", :status=>"Full", :charge=>100.0, :charging=>true, :discharging=>false, :full=>true}

	LinuxStat::Battery.status
	=> "Full"

	LinuxStat::Battery.technology
	=> "Li-ion"

	

LinuxStat::CPU

	LinuxStat::CPU.count
	=> 4

	LinuxStat::CPU.cur_freq
	=> [2000006, 1999996, 2000043, 2000016]

	LinuxStat::CPU.max_freq
	=> [2000000, 2000000, 2000000, 2000000]

	LinuxStat::CPU.model
	=> "Intel(R) Core(TM) i3-6006U CPU @ 2.00GHz"

	LinuxStat::CPU.stat
	=> {0=>0.0, 1=>0.0, 2=>0.0, 3=>0.0, 4=>50.0}

	LinuxStat::CPU.total_usage
	=> 40.0

	LinuxStat::CPU.usage
	=> 0.0

	LinuxStat::CPU.usages
	=> {0=>0.0, 1=>0.0, 2=>0.0, 3=>0.0, 4=>0.0}

	

LinuxStat::Filesystem

	LinuxStat::Filesystem.available
	=> 44319854592

	LinuxStat::Filesystem.free
	=> 44319854592

	LinuxStat::Filesystem.stat
	=> {:total=>119981191168, :free=>44319854592, :used=>75661336576}

	LinuxStat::Filesystem.stat_raw
	=> {:block_size=>4096, :fragment_size=>4096, :blocks=>29292283, :block_free=>10820277, :block_avail_unpriv=>10820277, :inodes=>58612160, :free_inodes=>56809150, :filesystem_id=>2050, :mount_flags=>1024, :max_filename_length=>255}

	LinuxStat::Filesystem.total
	=> 119981191168

	LinuxStat::Filesystem.used
	=> 75661336576

	

LinuxStat::Kernel

	LinuxStat::Kernel.build_date
	=> 2020-11-20 07:44:55 +0000

	LinuxStat::Kernel.build_date_string
	=> "20 Nov 2020 07:44:55 +0000"

	LinuxStat::Kernel.build_user
	=> "souravgoswami@archlinux"

	LinuxStat::Kernel.clk_tck
	=> 100

	LinuxStat::Kernel.compiler
	=> [:gcc, "10.2.0"]

	LinuxStat::Kernel.compiler_version
	=> "10.2.0"

	LinuxStat::Kernel.release
	=> "5.9.9-xanmod1-1"

	LinuxStat::Kernel.string
	=> "Linux version 5.9.9-xanmod1-1 (souravgoswami@archlinux) (gcc (GCC) 10.2.0, GNU ld (GNU Binutils) 2.35.1) #1 SMP PREEMPT Fri, 20 Nov 2020 07:44:55 +0000"

	LinuxStat::Kernel.ticks
	=> 100

	LinuxStat::Kernel.version
	=> "5.9.9-xanmod1-1"

	

LinuxStat::Memory

	LinuxStat::Memory.available
	=> 546856

	LinuxStat::Memory.percent_available
	=> 14.26

	LinuxStat::Memory.percent_used
	=> 85.74

	LinuxStat::Memory.stat
	=> {:total=>3836236, :used=>3289380, :available=>546856, :percent_used=>85.74, :percent_available=>14.26}

	LinuxStat::Memory.total
	=> 3836236

	LinuxStat::Memory.used
	=> 3289380

	

LinuxStat::Mounts

	LinuxStat::Mounts.device_stat
	=> {:mountpoint=>"/", :total=>119981191168, :free=>44319854592, :available=>44319854592, :used=>75661336576, :percent_used=>63.06, :percent_free=>36.94, :percent_available=>36.94}

	LinuxStat::Mounts.devices_stat
	=> {"proc"=>{:mountpoint=>"/proc", :total=>0, :free=>0, :available=>0, :used=>0, :percent_used=>NaN, :percent_free=>NaN, :percent_available=>NaN}, "sys"=>{:mountpoint=>"/sys", :total=>0, :free=>0, :available=>0, :used=>0, :percent_used=>NaN, :percent_fre...

	LinuxStat::Mounts.list
	=> ["proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0", "sys /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0", "dev /dev devtmpfs rw,nosuid,relatime,size=1892904k,nr_inodes=473226,mode=755 0 0", "run /run tmpfs rw,nosuid,nodev,relatime,mode=755 0 0", "...

	LinuxStat::Mounts.list_devices
	=> ["proc", "sys", "dev", "run", "/dev/sda2", "securityfs", "tmpfs", "devpts", "tmpfs", "cgroup2", "cgroup", "pstore", "none", "cgroup", "cgroup", "cgroup", "cgroup", "cgroup", "cgroup", "cgroup", "cgroup", "cgroup", "cgroup", "cgroup", "systemd-1", "mqu...

	LinuxStat::Mounts.list_devices_mount_point
	=> {"proc"=>"/proc", "sys"=>"/sys", "dev"=>"/dev", "run"=>"/run", "/dev/sda2"=>"/", "securityfs"=>"/sys/kernel/security", "tmpfs"=>"/run/user/1000", "devpts"=>"/dev/pts", "cgroup2"=>"/sys/fs/cgroup/unified", "cgroup"=>"/sys/fs/cgroup/blkio", "pstore"=>"/...

	LinuxStat::Mounts.mount_point
	=> "/"

	LinuxStat::Mounts.root
	=> "/dev/sda2"

	LinuxStat::Mounts.root_fs
	=> "xfs"

	LinuxStat::Mounts.root_mount_options
	=> "rw,noatime,attr2,inode64,logbufs=8,logbsize=32k,noquota"

	LinuxStat::Mounts.tmpfs
	=> {"/dev/shm"=>"tmpfs /dev/shm tmpfs rw,nosuid,nodev 0 0", "/sys/fs/cgroup"=>"tmpfs /sys/fs/cgroup tmpfs ro,nosuid,nodev,noexec,size=4096k,nr_inodes=1024,mode=755 0 0", "/cache"=>"tmpfs /cache tmpfs rw,nosuid,nodev,relatime,size=2097152k 0 0", "/ramdisk...

	

LinuxStat::Net

	LinuxStat::Net.current_usage
	=> {:received=>0.0, :transmitted=>0.0}

	LinuxStat::Net.ipv4_private
	=> "192.168.0.102"

	LinuxStat::Net.total_bytes
	=> {:received=>1244270076, :transmitted=>103084409}

	LinuxStat::Net.total_bytes_received
	=> 1244270076

	LinuxStat::Net.total_bytes_transmitted
	=> 103084409

	LinuxStat::Net.usage
	=> {:received=>0.0, :transmitted=>0.0}

	

LinuxStat::OS

	LinuxStat::OS.bits
	=> 64

	LinuxStat::OS.distribution
	=> "Arch Linux"

	LinuxStat::OS.hostname
	=> "archlinux"

	LinuxStat::OS.lsb_release
	=> {:LSB_VERSION=>"1.4", :DISTRIB_ID=>"Arch", :DISTRIB_RELEASE=>"rolling", :DISTRIB_DESCRIPTION=>"Arch Linux"}

	LinuxStat::OS.machine
	=> "x86_64"

	LinuxStat::OS.nodename
	=> "archlinux"

	LinuxStat::OS.os_release
	=> {:NAME=>"Arch Linux", :PRETTY_NAME=>"Arch Linux", :ID=>"arch", :BUILD_ID=>"rolling", :ANSI_COLOR=>"38;2;23;147;209", :HOME_URL=>"https://www.archlinux.org/", :DOCUMENTATION_URL=>"https://wiki.archlinux.org/", :SUPPORT_URL=>"https://bbs.archlinux.org/"...

	LinuxStat::OS.uptime
	=> {:hour=>12, :minute=>31, :second=>39.76}

	

LinuxStat::Process

	LinuxStat::Process.count
	=> 207

	LinuxStat::Process.idle
	=> [3, 4, 6, 9, 12, 23, 30, 37, 39, 49, 102, 103, 104, 106, 107, 108, 109, 110, 117, 118, 120, 122, 131, 134, 140, 152, 153, 168, 170, 173, 174, 177, 178, 183, 184, 185, 186, 187, 188, 230, 267, 374, 376, 10126, 11712, 11713, 11714, 11715, 11716, 11717,...

	LinuxStat::Process.list
	=> [1, 2, 3, 4, 6, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 30, 31, 32, 33, 34, 35, 37, 38, 39, 40, 41, 42, 46, 47, 48, 49, 50, 51, 52, 102, 103, 104, 106, 107, 108, 109, 110, 112, 114, 115, 117, 118, 120, 122, 131, 134,...

	LinuxStat::Process.names
	=> {1=>"systemd", 2=>"kthreadd", 3=>"rcu_gp", 4=>"rcu_par_gp", 6=>"kworker/0:0H-kblockd", 9=>"mm_percpu_wq", 10=>"ksoftirqd/0", 11=>"rcuc/0", 12=>"rcu_preempt", 13=>"rcub/0", 14=>"migration/0", 15=>"idle_inject/0", 16=>"cpuhp/0", 17=>"cpuhp/1", 18=>"idle...

	LinuxStat::Process.running
	=> [35289]

	LinuxStat::Process.sleeping
	=> [1, 2, 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 24, 25, 26, 27, 28, 31, 32, 33, 34, 35, 38, 40, 41, 42, 46, 47, 48, 50, 51, 52, 112, 114, 115, 167, 169, 189, 218, 233, 303, 306, 307, 308, 310, 311, 312, 313, 321, 324, 329, 330, 402, 405, 407, 408,...

	LinuxStat::Process.types
	=> {1=>:sleeping, 2=>:sleeping, 3=>:idle, 4=>:idle, 6=>:idle, 9=>:idle, 10=>:sleeping, 11=>:sleeping, 12=>:idle, 13=>:sleeping, 14=>:sleeping, 15=>:sleeping, 16=>:sleeping, 17=>:sleeping, 18=>:sleeping, 19=>:sleeping, 20=>:sleeping, 21=>:sleeping, 23=>:i...

	LinuxStat::Process.zombie
	=> []

	

LinuxStat::ProcessInfo

	LinuxStat::ProcessInfo.cmdline
	=> "ruby /usr/bin/linuxstat.rb -html"

	LinuxStat::ProcessInfo.command_name
	=> "ruby"

	LinuxStat::ProcessInfo.cpu_stat
	=> {:cpu_usage=>0.0, :threads=>1, :last_executed_cpu=>3}

	LinuxStat::ProcessInfo.cpu_usage
	=> 0.0

	LinuxStat::ProcessInfo.gid
	=> {:real=>1000, :effective=>1000, :saved_set=>1000, :filesystem_uid=>1000}

	LinuxStat::ProcessInfo.last_executed_cpu
	=> 3

	LinuxStat::ProcessInfo.mem_stat
	=> {:memory=>12140.544, :virtual_memory=>83947.52, :resident_memory=>17985.536}

	LinuxStat::ProcessInfo.memory
	=> 12140.544

	LinuxStat::ProcessInfo.nice
	=> 0

	LinuxStat::ProcessInfo.owner
	=> "sourav"

	LinuxStat::ProcessInfo.resident_memory
	=> 17985.536

	LinuxStat::ProcessInfo.running_time
	=> 0.8300000000017462

	LinuxStat::ProcessInfo.start_time
	=> 2020-12-16 23:50:37.318675484 +0530

	LinuxStat::ProcessInfo.state
	=> "R"

	LinuxStat::ProcessInfo.threads
	=> 1

	LinuxStat::ProcessInfo.total_io
	=> {:read_bytes=>5660672, :write_bytes=>0}

	LinuxStat::ProcessInfo.uid
	=> {:real=>1000, :effective=>1000, :saved_set=>1000, :filesystem_uid=>1000}

	LinuxStat::ProcessInfo.virtual_memory
	=> 83947.52

	

LinuxStat::Swap

	LinuxStat::Swap.any?
	=> true

	LinuxStat::Swap.available
	=> 3078396

	LinuxStat::Swap.list
	=> {"/dev/zram0"=>[:partition, 4194300, 1115904, -2]}

	LinuxStat::Swap.percent_available
	=> 73.39

	LinuxStat::Swap.percent_used
	=> 26.61

	LinuxStat::Swap.stat
	=> {:total=>4194300, :used=>1115904, :available=>3078396, :percent_used=>26.61, :percent_available=>73.39}

	LinuxStat::Swap.total
	=> 4194300

	LinuxStat::Swap.used
	=> 1115904

	

LinuxStat::Sysconf

	LinuxStat::Sysconf.child_max
	=> 2000000

	LinuxStat::Sysconf.get_euid
	=> 1000

	LinuxStat::Sysconf.get_gid
	=> 1000

	LinuxStat::Sysconf.get_login
	=> "sourav"

	LinuxStat::Sysconf.get_uid
	=> 1000

	LinuxStat::Sysconf.get_user
	=> "sourav"

	LinuxStat::Sysconf.hostname_max
	=> 64

	LinuxStat::Sysconf.login_name_max
	=> 256

	LinuxStat::Sysconf.open_max
	=> 1024

	LinuxStat::Sysconf.pagesize
	=> 4096

	LinuxStat::Sysconf.posix_version
	=> 200809

	LinuxStat::Sysconf.sc_clk_tck
	=> 100

	LinuxStat::Sysconf.stream_max
	=> 16

	LinuxStat::Sysconf.tty_name_max
	=> 32

	

LinuxStat::Uname

	LinuxStat::Uname.machine
	=> "x86_64"

	LinuxStat::Uname.nodename
	=> "archlinux"

	LinuxStat::Uname.release
	=> "5.9.9-xanmod1-1"

	LinuxStat::Uname.sysname
	=> "Linux"

	LinuxStat::Uname.version
	=> "#1 SMP PREEMPT Fri, 20 Nov 2020 07:44:55 +0000"

	

LinuxStat::User

	LinuxStat::User.get_current_user
	=> "sourav"

	LinuxStat::User.get_euid
	=> 1000

	LinuxStat::User.get_gid
	=> 1000

	LinuxStat::User.get_login
	=> "sourav"

	LinuxStat::User.get_uid
	=> 1000

	LinuxStat::User.get_user
	=> "sourav"

	LinuxStat::User.gid_by_username
	=> 1000

	LinuxStat::User.gids
	=> {:root=>0, :bin=>1, :daemon=>2, :mail=>12, :ftp=>11, :http=>33, :nobody=>65534, :dbus=>81, :"systemd-journal-remote"=>982, :"systemd-network"=>981, :"systemd-resolve"=>980, :"systemd-timesync"=>979, :"systemd-coredump"=>978, :uuidd=>68, :avahi=>977, :...

	LinuxStat::User.home_by_gid
	=> "/home/sourav"

	LinuxStat::User.home_by_username
	=> "/home/sourav"

	LinuxStat::User.home_directories
	=> {:root=>"/root", :bin=>"/", :daemon=>"/", :mail=>"/var/spool/mail", :ftp=>"/srv/ftp", :http=>"/srv/http", :nobody=>"/", :dbus=>"/", :"systemd-journal-remote"=>"/", :"systemd-network"=>"/", :"systemd-resolve"=>"/", :"systemd-timesync"=>"/", :"systemd-c...

	LinuxStat::User.homes_by_uid
	=> ["/home/sourav"]

	LinuxStat::User.ids
	=> {:root=>{:uid=>0, :gid=>0}, :bin=>{:uid=>1, :gid=>1}, :daemon=>{:uid=>2, :gid=>2}, :mail=>{:uid=>8, :gid=>12}, :ftp=>{:uid=>14, :gid=>11}, :http=>{:uid=>33, :gid=>33}, :nobody=>{:uid=>65534, :gid=>65534}, :dbus=>{:uid=>81, :gid=>81}, :"systemd-journal...

	LinuxStat::User.list
	=> ["root", "bin", "daemon", "mail", "ftp", "http", "nobody", "dbus", "systemd-journal-remote", "systemd-network", "systemd-resolve", "systemd-timesync", "systemd-coredump", "uuidd", "avahi", "colord", "git", "lxdm", "polkitd", "rtkit", "usbmux", "sourav...

	LinuxStat::User.uid_by_username
	=> 1000

	LinuxStat::User.uids
	=> {:root=>0, :bin=>1, :daemon=>2, :mail=>8, :ftp=>14, :http=>33, :nobody=>65534, :dbus=>81, :"systemd-journal-remote"=>982, :"systemd-network"=>981, :"systemd-resolve"=>980, :"systemd-timesync"=>979, :"systemd-coredump"=>978, :uuidd=>68, :avahi=>977, :c...

	LinuxStat::User.username_by_gid
	=> "sourav"

	LinuxStat::User.usernames_by_uid
	=> ["sourav"]

	
Seeing the list, you might think I ran all methods and typed them all... Actually no... There's a script that can do that all for you... It can even calculate the time each method takes to execute and also generate readme type of file! Here's the file: bin/linuxstat.rb

Return Types

The returns types are clear in this gem.
  • In general, if a method returns either a Float or a Integer or a Time, it will return a Float or Integer or Time in all cases. But if the status isn't available, it will return nil.
  • If the method returns a Hash / Array, it will return return Hash / Array in all cases. If the status isn't available, it will return an empty Hash / Array.
  • If the method returns a String, it will return return String in all cases. If the status isn't available, it will return an empty frozen String.
  • It doesn't have implementation of any Error that gets raised in runtime for the ease of use.
  • If you need to check some stat that returns an integer or float, and you get nil, you know it's not available, so you can work accordingly. But if you need the integer or float value in 0 to whatever format, you can use the .to_i or .to_f method on the object, nil will get converted to number then.

Caveats

  1. No OS Check: This gem offers a lot of stuff. But the biggest caveat is that it doesn't check what the host OS is. If you run this on Windows or Mac or even any Unix that is not Linux this gem may crash directly. Hence the name linux_stat. But as long as you are using Linux, it will always work no matter what your distribution is or if the system is old or new. So the user of this gem has to check what the host OS is, and load the gem accordingly. For example:
    				require 'linux_stat' if RbConfig::CONFIG['host_os'].to_s[/linux/]
    			
  2. The 2nd problem is that it only supports from Ruby 2.5. The current version of Ruby in 2020 is 2.7. It looks like that it will probably keep supporting Ruby 2.5 for some time now, but if you are using Ruby < 2.5, you might not be able to use this gem at all...

Let me know your thoughts about this gem below!

Comments