Module: LinuxStat::ProcessInfo
- Defined in:
- lib/linux_stat/process_info.rb
Overview
Shows various information about a process that is either running, sleeping, idle or a zombie. Most methods can take a PID, but some uses polling to calculate something, they can accept options instead of arguments. Consult the documentation on the specific methods for more details on that.
Class Method Summary collapse
-
.cmdline(pid = $$) ⇒ Object
cmdline(pid = $$).
-
.command_name(pid = $$) ⇒ Object
command_name(pid = $$) Not to be confused with process_name It just splits the cmdline to show the command name.
-
.cpu_stat(pid: $$, sleep: ticks_to_ms_t5) ⇒ Object
cpu_stat(pid: $$, sleep: 1.0 / LinuxStat::Sysconf.sc_clk_tck * 5).
-
.cpu_usage(pid: $$, sleep: ticks_to_ms_t5) ⇒ Object
cpu_usage(pid: $$, sleep: 1.0 / LinuxStat::Sysconf.sc_clk_tck * 5).
-
.gid(pid = $$) ⇒ Object
gid(pid = $$).
-
.last_executed_cpu(pid = $$) ⇒ Object
last_executed_cpu(pid = $$).
-
.mem_stat(pid = $$) ⇒ Object
mem_stat(pid = $$).
-
.memory(pid = $$) ⇒ Object
memory(pid = $$).
-
.nice(pid = $$) ⇒ Object
nice(pid = $$) Returns the nice of the process.
-
.nproc(pid = $$) ⇒ Object
(also: count_cpu)
nproc(pid = $$) Returns the cpu allocated to the process.
-
.owner(pid = $$) ⇒ Object
owner(pid = $$).
-
.process_name(pid = $$) ⇒ Object
process_name(pid = $$) It shows the filename of the command Sometimes the filename is stripped.
-
.resident_memory(pid = $$) ⇒ Object
resident_memory(pid = $$).
-
.running_time(pid = $$) ⇒ Object
running_time(pid = $$).
-
.start_time(pid = $$) ⇒ Object
start_time(pid = $$).
-
.start_time_epoch(pid = $$) ⇒ Object
start_time_epoch(pid = $$).
-
.state(pid = $$) ⇒ Object
state(pid = $$) Returns the state of the process as a frozen String.
-
.thread_usage(pid: $$, sleep: ticks_to_ms_t5) ⇒ Object
thread_usage(pid: $$, sleep: 1.0 / LinuxStat::Sysconf.sc_clk_tck * 5).
-
.threads(pid = $$) ⇒ Object
threads(pid = $$).
-
.total_io(pid = $$) ⇒ Object
total_io(pid = $$).
-
.uid(pid = $$) ⇒ Object
uid(pid = $$).
-
.virtual_memory(pid = $$) ⇒ Object
virtual_memory(pid = $$).
Class Method Details
.cmdline(pid = $$) ⇒ Object
cmdline(pid = $$)
Where pid is the process ID.
By default it is the id of the current process ($$)
It retuns the total command of the process.
The output is String. For example:
LinuxStat::ProcessInfo.cmdline
"ruby -r linux_stat -e p LinuxStat::ProcessInfo.cmdline"
If the info isn’t available it will return an empty frozen String.
61 62 63 64 65 66 67 68 |
# File 'lib/linux_stat/process_info.rb', line 61 def cmdline(pid = $$) file = "/proc/#{pid}/cmdline".freeze return ''.freeze unless File.readable?(file) _cmdline = IO.read(file) _cmdline.gsub!(?\u0000, ?\s) _cmdline.tap(&:strip!) end |
.command_name(pid = $$) ⇒ Object
command_name(pid = $$)
Not to be confused with process_name It just splits the cmdline to show the command name
Where pid is the process ID.
By default it is the id of the current process ($$)
It retuns the total command name of the process.
The output is String. For example:
LinuxStat::ProcessInfo.command_name
"ruby"
If the info isn’t available it will return an empty frozen String.
87 88 89 90 91 92 93 |
# File 'lib/linux_stat/process_info.rb', line 87 def command_name(pid = $$) # Do note that the /proc/ppid/comm may not contain the full name # It's limited by TASK_COMM_LEN (16) characters c = cmdline(pid).split[0] return ''.freeze unless c File.split(c)[-1] end |
.cpu_stat(pid: $$, sleep: ticks_to_ms_t5) ⇒ Object
cpu_stat(pid: $$, sleep: 1.0 / LinuxStat::Sysconf.sc_clk_tck * 5)
Where pid is the process ID and sleep time is the interval between measurements.
By default it is the id of the current process ($$), and sleep is LinuxStat::Sysconf.sc_clk_tck
The smallest amount of available sleep time is 1.0 / LinuxStat::Sysconf.sc_clk_tck * 5.
-
Note 1:
-
Do note that the sleep time can slow down your application.
-
And it’s only needed for the cpu usage calculation.
It retuns the CPU usage, threads, and the last executed CPU in Hash.
For example:
LinuxStat::ProcessInfo.cpu_stat
=> {:cpu_usage=>0.0, :threads=>1, :last_executed_cpu=>1}
But if the info isn’t available, it will return an empty Hash.
The :cpu_usage is in percentage. It’s also divided with the number of CPU.
:cpu_usage for example, will return 25.0 if the CPU count is 4, and the process is using 100% of a thread / core.
A value of 100.0 indicates it is using 100% processing power available to the system.
The :threads returns the number of threads for the process. The value is a Integer.
-
Note 2:
-
If you just need the CPU usage run LinuxStat::ProcessInfo.cpu_usage(pid = $$)
-
If you just need the threads run LinuxStat::ProcessInfo.threads(pid = $$)
-
If you just need the last executed CPU run LinuxStat::ProcessInfo.last_executed_cpu(pid = $$)
-
Running this method is slower and it opens multiple files at once
Only use this method if you need all of the data at once, in such case, it’s more efficient to use this method.
The :last_executed_cpu also returns an Integer indicating the last executed cpu of the process.
284 285 286 287 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 314 315 316 317 318 319 320 321 322 |
# File 'lib/linux_stat/process_info.rb', line 284 def cpu_stat(pid: $$, sleep: ticks_to_ms_t5) file = "/proc/#{pid}/stat" ticks = get_ticks return {} unless File.readable?(file) stat = IO.read(file).split(/(\(.*\))/)[-1] &.split return {} unless stat utime, stime, starttime = *stat.values_at(11, 12, 19).map(&:to_f) uptime = IO.read('/proc/uptime'.freeze).to_f * ticks total_time = utime + stime idle1 = uptime - starttime - total_time sleep(sleep) return {} unless File.readable?(file) stat = IO.read(file).split(/(\(.*\))/)[-1] &.split return {} unless stat utime2, stime2, starttime2 = *stat.values_at(11, 12, 19).map(&:to_f) uptime = IO.read('/proc/uptime'.freeze).to_f * ticks total_time2 = utime2 + stime2 idle2 = uptime - starttime2 - total_time2 totald = idle2.+(total_time2).-(idle1 + total_time) cpu_u = totald.-(idle2 - idle1).fdiv(totald).abs.*(100)./(cpu_count) { cpu_usage: cpu_u > 100 ? 100.0 : cpu_u.round(2), threads: stat[17].to_i, last_executed_cpu: stat[36].to_i } end |
.cpu_usage(pid: $$, sleep: ticks_to_ms_t5) ⇒ Object
cpu_usage(pid: $$, sleep: 1.0 / LinuxStat::Sysconf.sc_clk_tck * 5)
Where pid is the process ID and sleep time is the interval between measurements.
By default it is the id of the current process ($$), and sleep is 1.0 / LinuxStat::Sysconf.sc_clk_tck * 5
The smallest amount of available sleep time is LinuxStat::Sysconf.sc_clk_tck.
It retuns the CPU usage as Float.
For example:
LinuxStat::ProcessInfo.cpu_usage
=> 10.0
10.0 means it’s using 10% of the total processing power of the system.
The value is divided with the configured number of CPU and not online CPU.
A value of 100.0 indicates it is using 100% processing power available to the system.
But if the info isn’t available, it will return nil.
This method is more efficient than running LinuxStat::ProcessInfo.cpu_stat()
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 |
# File 'lib/linux_stat/process_info.rb', line 350 def cpu_usage(pid: $$, sleep: ticks_to_ms_t5) file = "/proc/#{pid}/stat" ticks = get_ticks return nil unless File.readable?(file) stat = IO.read(file).split(/(\(.*\))/)[-1] &.split return nil unless stat utime, stime, starttime = *stat.values_at(11, 12, 19).map(&:to_f) uptime = IO.read('/proc/uptime'.freeze).to_f * ticks total_time = utime + stime idle1 = uptime - starttime - total_time sleep(sleep) return nil unless File.readable?(file) stat = IO.read(file).split(/(\(.*\))/)[-1] &.split return nil unless stat utime2, stime2, starttime2 = *stat.values_at(11, 12, 19).map(&:to_f) uptime = IO.read('/proc/uptime'.freeze).to_f * ticks total_time2 = utime2 + stime2 idle2 = uptime - starttime2 - total_time2 totald = idle2.+(total_time2).-(idle1 + total_time) u = totald.-(idle2 - idle1).fdiv(totald).abs.*(100)./(cpu_count) u > 100 ? 100.0 : u.round(2) end |
.gid(pid = $$) ⇒ Object
gid(pid = $$)
returns the GIDs of the process as an Hash containing the following data:
:real, :effective, :saved_set, :filesystem_uid
If the info isn’t available or the argument passed doesn’t exist as a process ID, it will return an empty Hash.
525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 |
# File 'lib/linux_stat/process_info.rb', line 525 def gid(pid = $$) file = "/proc/#{pid}/status".freeze return nil unless File.readable?(file) data = IO.foreach(file.freeze).find { |x| x[/Gid.*\d*/] }.split.drop(1) { real: data[0].to_i, effective: data[1].to_i, saved_set: data[2].to_i, filesystem_uid: data[3].to_i } end |
.last_executed_cpu(pid = $$) ⇒ Object
last_executed_cpu(pid = $$)
Where pid is the process ID.
By default it is the id of the current process ($$)
It retuns the last executed CPU in Integer.
For example:
LinuxStat::ProcessInfo.last_executed_cpu
=> 2
But if the info isn’t available, it will return nil.
This method is way more efficient than running LinuxStat::ProcessInfo.cpu_stat()
487 488 489 490 491 492 493 |
# File 'lib/linux_stat/process_info.rb', line 487 def last_executed_cpu(pid = $$) file = "/proc/#{pid}/stat".freeze return nil unless File.readable?(file) data = IO.read(file).split(/(\(.*\))/)[-1] &.split &.at(36) data ? data.to_i : nil end |
.mem_stat(pid = $$) ⇒ Object
mem_stat(pid = $$)
Where pid is the process ID.
By default it is the id of the current process ($$)
It retuns the memory, virtual memory, and resident memory of the process.
All values are in kilobytes.
The output is a Hash. For example:
LinuxStat::ProcessInfo.mem_stat
{:memory=>8515.584, :virtual_memory=>79781.888, :resident_memory=>13955.072}
-
Note:
-
If you need only memory usage of a process, run LinuxStat::ProcessInfo.memory(pid)
-
If you need only virtual memory for a process, run LinuxStat::ProcessInfo.virtual_memory(pid)
-
If you need only resident memory of a process, run LinuxStat::ProcessInfo.resident_memory(pid)
This method opens opens multiple files.
But if you need all of the info, then running this method once is efficient.
If the info isn’t available it will return an empty Hash.
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/linux_stat/process_info.rb', line 151 def mem_stat(pid = $$) statm = "/proc/#{pid}/statm".freeze return {} unless File.readable?(statm) data = IO.read(statm).split _rss_anon = (data[1] && data[2]) ? data[1].to_i.-(data[2].to_i).*(pagesize).fdiv(1000) : nil _virtual_memory = data[0] ? data[0].to_i*(pagesize).fdiv(1000) : nil _resident_memory = data[1] ? data[1].to_i.*(pagesize).fdiv(1000) : nil { memory: _rss_anon, virtual_memory: _virtual_memory, resident_memory: _resident_memory } end |
.memory(pid = $$) ⇒ Object
memory(pid = $$)
Where pid is the process ID.
By default it is the id of the current process ($$)
It retuns the memory of the process. The value is in kilobytes.
The output is an Integer. For example:
LinuxStat::ProcessInfo.memory
8523.776
If the info isn’t available it will return nil.
184 185 186 187 188 189 190 |
# File 'lib/linux_stat/process_info.rb', line 184 def memory(pid = $$) file = "/proc/#{pid}/statm".freeze return nil unless File.readable?(file) data = IO.read(file).split (data[1] && data[2]) ? data[1].to_i.-(data[2].to_i).*(pagesize).fdiv(1000) : nil end |
.nice(pid = $$) ⇒ Object
nice(pid = $$)
Returns the nice of the process
The output value is an Integer ranging from -20 to 19
-20 means the process has high priority, and 19 means the process has low priority
If the info isn’t available or the argument passed doesn’t exist as a process ID, it will return nil.
672 673 674 675 676 677 678 679 680 |
# File 'lib/linux_stat/process_info.rb', line 672 def nice(pid = $$) file = "/proc/#{pid}/stat" return nil unless File.readable?(file) stat = IO.read(file).split(/(\(.*\))/)[-1] &.split return nil unless stat stat[16].to_i end |
.nproc(pid = $$) ⇒ Object Also known as: count_cpu
nproc(pid = $$)
Returns the cpu allocated to the process.
The output value is an Integer.
For example:
$ taskset -c 0 irb
irb(main):001:0> require 'linux_stat'
=> true
irb(main):002:0> LinuxStat::ProcessInfo.nproc
=> 1
irb(main):003:0> LinuxStat::ProcessInfo.nproc 11562
=> 3
irb(main):004:0> LinuxStat::ProcessInfo.nproc 12513
=> 4
If the info isn’t available or the argument passed doesn’t exist as a process ID, it will return nil.
708 709 710 |
# File 'lib/linux_stat/process_info.rb', line 708 def nproc(pid = $$) LinuxStat::Nproc.count_cpu_for_pid(pid) end |
.owner(pid = $$) ⇒ Object
owner(pid = $$)
Returns the owner of the process But if the status is not available, it will return an empty frozen String.
546 547 548 549 550 551 552 553 554 555 |
# File 'lib/linux_stat/process_info.rb', line 546 def owner(pid = $$) file = "/proc/#{pid}/status".freeze return ''.freeze unless File.readable?(file) gid = IO.foreach(file.freeze).find { |x| x[/Gid.*\d*/] }.split.drop(1)[2].to_i LinuxStat::User.username_by_gid(gid) end |
.process_name(pid = $$) ⇒ Object
process_name(pid = $$)
It shows the filename of the command Sometimes the filename is stripped
Where pid is the process ID.
By default it is the id of the current process ($$)
It retuns the total command name of the process.
The output is String. For example:
LinuxStat::ProcessInfo.process_name
"ruby"
If the info isn’t available it will return an empty frozen String.
112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/linux_stat/process_info.rb', line 112 def process_name(pid = $$) file = "/proc/#{pid}/stat".freeze return command_name unless File.readable?(file) name = IO.read(file).split(/(\(.*\))/) &.[](1) &.[](1..-2) if name && name.length > 0 && name.length < 15 name else command_name end end |
.resident_memory(pid = $$) ⇒ Object
resident_memory(pid = $$)
Where pid is the process ID.
By default it is the id of the current process ($$)
It retuns the resident memory for the process.
The value is in kilobytes.
The output is an Integer. For example:
LinuxStat::ProcessInfo.cpu_stat
=> 13996.032
If the info isn’t available it will return nil.
234 235 236 237 238 239 240 |
# File 'lib/linux_stat/process_info.rb', line 234 def resident_memory(pid = $$) file = "/proc/#{pid}/statm".freeze return nil unless File.readable?(file) _vm_rss = IO.read(file).split[1] _vm_rss ? _vm_rss.to_i.*(pagesize).fdiv(1000) : nil end |
.running_time(pid = $$) ⇒ Object
running_time(pid = $$)
Returns the time (in seconds, as Float) the process is running for.
For example:
LinuxStat::ProcessInfo.running_time 14183
=> 1947.61
It always rounds the float number upto 2 decimal places
If the info isn’t available or the argument passed doesn’t exist as a process ID, it will return nil.
621 622 623 624 625 626 627 628 629 630 631 632 633 |
# File 'lib/linux_stat/process_info.rb', line 621 def running_time(pid = $$) stat_file = "/proc/#{pid}/stat".freeze uptime = "/proc/uptime".freeze @@u_readable ||= File.readable?(uptime) return nil unless @@u_readable && File.readable?(stat_file) stat = IO.read(stat_file).split(/(\(.*\))/)[-1] &.split return nil unless stat IO.foreach(uptime, ' '.freeze).next.to_f .-(stat[19].to_f / get_ticks).round(2) end |
.start_time(pid = $$) ⇒ Object
start_time(pid = $$)
Returns the time (as Time object) the process was started.
For example:
LinuxStat::ProcessInfo.start_time 14183
=> 2020-12-16 13:31:43 +0000
If the info isn’t available or the argument passed doesn’t exist as a process ID, it will return nil.
The timezone returned based on current TZ. Thus the timezone could be affected by changing the ENV variable.
Don’t trust the timezone returned by the time.
602 603 604 605 606 |
# File 'lib/linux_stat/process_info.rb', line 602 def start_time(pid = $$) # Getting two Time objects and dealing with floating point numbers # Just to make sure the time goes monotonically Time.at(start_time_epoch(pid)) end |
.start_time_epoch(pid = $$) ⇒ Object
start_time_epoch(pid = $$)
Returns the epoch time (as Integer) the process was started.
For example:
LinuxStat::ProcessInfo.start_time_epoch 526
=> 1608097744
If the info isn’t available or the argument passed doesn’t exist as a process ID, it will return nil.
568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 |
# File 'lib/linux_stat/process_info.rb', line 568 def start_time_epoch(pid = $$) stat_file = "/proc/#{pid}/stat".freeze uptime = "/proc/uptime".freeze @@u_readable ||= File.readable?(uptime) return nil unless @@u_readable && File.readable?(stat_file) stat = IO.read(stat_file).split(/(\(.*\))/)[-1] &.split return nil unless stat u = IO.foreach(uptime, ' '.freeze).next.to_f st = stat[19].to_f / get_ticks # Getting two Time objects and dealing with floating point numbers # Just to make sure the time goes monotonically Time.now.-(u - st).to_i end |
.state(pid = $$) ⇒ Object
state(pid = $$)
Returns the state of the process as a frozen String
-
A process could have multiple states:
-
S => Sleeping
-
R => Running
-
I => Idle
-
Z => Zombie
It returns any one of them.
If the info isn’t available or the argument passed doesn’t exist as a process ID, it will return an empty String.
653 654 655 656 657 658 659 660 661 |
# File 'lib/linux_stat/process_info.rb', line 653 def state(pid = $$) file = "/proc/#{pid}/stat".freeze return ''.freeze unless File.readable?(file) stat = IO.read(file).split(/(\(.*\))/)[-1] return '' unless stat stat[/\s.+?/].strip end |
.thread_usage(pid: $$, sleep: ticks_to_ms_t5) ⇒ Object
thread_usage(pid: $$, sleep: 1.0 / LinuxStat::Sysconf.sc_clk_tck * 5)
Where pid is the process ID and sleep time is the interval between measurements.
By default it is the id of the current process ($$), and sleep is 1.0 / LinuxStat::Sysconf.sc_clk_tck * 5
The smallest amount of available sleep time is LinuxStat::Sysconf.sc_clk_tck.
It retuns the per core CPU usage as Float.
For example:
LinuxStat::ProcessInfo.core_usage
=> 200.0
A value of 100.0 indicates it is using 100% processing power of a core.
The value could be 0 to (100 * the number of CPU threads (including hyperthreading) in the system)
But if the info isn’t available, it will return nil.
407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 |
# File 'lib/linux_stat/process_info.rb', line 407 def thread_usage(pid: $$, sleep: ticks_to_ms_t5) file = "/proc/#{pid}/stat" ticks = get_ticks return nil unless File.readable?(file) stat = IO.read(file).split(/(\(.*\))/)[-1] &.split return nil unless stat utime, stime, starttime = *stat.values_at(11, 12, 19).map(&:to_f) uptime = IO.read('/proc/uptime'.freeze).to_f * ticks total_time = utime + stime idle1 = uptime - starttime - total_time sleep(sleep) return nil unless File.readable?(file) stat = IO.read(file).split(/(\(.*\))/)[-1] &.split return nil unless stat utime2, stime2, starttime2 = *stat.values_at(11, 12, 19).map(&:to_f) uptime = IO.read('/proc/uptime'.freeze).to_f * ticks total_time2 = utime2 + stime2 idle2 = uptime - starttime2 - total_time2 totald = idle2.+(total_time2).-(idle1 + total_time) u = totald.-(idle2 - idle1).fdiv(totald).abs.*(100) cpu_count_t100 = cpu_count * 100 u > cpu_count_t100 ? cpu_count_t100 : u.round(2) end |
.threads(pid = $$) ⇒ Object
threads(pid = $$)
Where pid is the process ID.
By default it is the id of the current process ($$)
It retuns the threads for the current process in Integer.
For example:
LinuxStat::ProcessInfo.threads
=> 2
But if the info isn’t available, it will return nil.
This method is way more efficient than running LinuxStat::ProcessInfo.cpu_stat()
462 463 464 465 466 467 468 |
# File 'lib/linux_stat/process_info.rb', line 462 def threads(pid = $$) file = "/proc/#{pid}/stat".freeze return nil unless File.readable?(file) data = IO.read(file).split(/(\(.*\))/)[-1] &.split &.at(17) data ? data.to_i : nil end |
.total_io(pid = $$) ⇒ Object
total_io(pid = $$)
Where pid is the process ID.
By default it is the id of the current process ($$)
It retuns the total read/write caused by a process.
The output is Hash.
For example:
LinuxStat::ProcessInfo.total_io
{:read_bytes=>0, :write_bytes=>0}
The output is only based on the total disk IO the process has done.
If the info isn’t available it will return an empty Hash.
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/linux_stat/process_info.rb', line 30 def total_io(pid = $$) return {} unless File.readable?("/proc/#{pid}/io".freeze) out = {} IO.readlines("/proc/#{pid}/io".freeze).each { |x| x.strip! if x[/^(read|write)_bytes:\s*\d*$/] splitted = x.split out.merge!(splitted[0].split(?:)[0].to_sym => splitted[-1].to_i) end } out end |
.uid(pid = $$) ⇒ Object
uid(pid = $$)
returns the UIDs of the process as an Array of Integers.
If the info isn’t available it returns an empty Array.
501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 |
# File 'lib/linux_stat/process_info.rb', line 501 def uid(pid = $$) file = "/proc/#{pid}/status".freeze return nil unless File.readable?(file) data = IO.foreach(file.freeze).find { |x| x[/Uid.*\d*/] }.to_s.split.drop(1) { real: data[0].to_i, effective: data[1].to_i, saved_set: data[2].to_i, filesystem_uid: data[3].to_i } end |
.virtual_memory(pid = $$) ⇒ Object
virtual_memory(pid = $$)
Where pid is the process ID.
By default it is the id of the current process ($$)
It retuns the virtual memory for the process.
The value is in kilobytes.
The output is an Integer. For example:
LinuxStat::ProcessInfo.virtual_memory
79781.888
If the info isn’t available it will return nil.
209 210 211 212 213 214 215 |
# File 'lib/linux_stat/process_info.rb', line 209 def virtual_memory(pid = $$) file = "/proc/#{pid}/statm".freeze return nil unless File.readable?(file) _virtual_memory = IO.read(file).split[0] _virtual_memory ? _virtual_memory.to_i.*(pagesize).fdiv(1000) : nil end |