linux_stat 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,7 @@ module LinuxStat
2
2
  module Filesystem
3
3
  class << self
4
4
  ##
5
- # = stat(fs = '/')
5
+ # = stat(fs = '.')
6
6
  #
7
7
  # Where fs is the directory of the file system (like / or /tmp/ or /run/media/thumbdrive).
8
8
  #
@@ -16,7 +16,7 @@ module LinuxStat
16
16
  # {:total=>119981191168, :free=>43155574784, :used=>76825616384, :available=>43155574784}
17
17
  #
18
18
  # If the stat can't be acquired, this method will return an empty Hash.
19
- def stat(fs = ?/.freeze)
19
+ def stat(fs = ?..freeze)
20
20
  s = stat_raw(fs)
21
21
  return {} if s.empty?
22
22
  s.default = 0
@@ -29,14 +29,14 @@ module LinuxStat
29
29
  end
30
30
 
31
31
  ##
32
- # = total(fs = '/')
32
+ # = total(fs = '.')
33
33
  #
34
34
  # Where fs is the directory of the file system (like / or /tmp/ or /run/media/thumbdrive).
35
35
  #
36
36
  # It returns the total size of a given disk in bytes.
37
37
  #
38
38
  # If the stat can't be acquired, this method will return nil.
39
- def total(fs = ?/.freeze)
39
+ def total(fs = ?..freeze)
40
40
  s = stat_raw(fs)
41
41
  return nil if s.empty?
42
42
  s.default = 0
@@ -44,7 +44,7 @@ module LinuxStat
44
44
  end
45
45
 
46
46
  ##
47
- # = free(fs = '/')
47
+ # = free(fs = '.')
48
48
  #
49
49
  # Where fs is the directory of the file system (like / or /tmp/ or /run/media/thumbdrive).
50
50
  #
@@ -55,7 +55,7 @@ module LinuxStat
55
55
  # Free returns the size of free blocks.
56
56
  #
57
57
  # If the stat can't be acquired, this method will return an empty Hash.
58
- def free(fs = ?/.freeze)
58
+ def free(fs = ?..freeze)
59
59
  s = stat_raw(fs)
60
60
  return nil if s.empty?
61
61
  s.default = 0
@@ -63,14 +63,14 @@ module LinuxStat
63
63
  end
64
64
 
65
65
  ##
66
- # = used(fs = '/')
66
+ # = used(fs = '.')
67
67
  #
68
68
  # Where fs is the directory of the file system (like / or /tmp/ or /run/media/thumbdrive).
69
69
  #
70
70
  # It returns the used space of a given disk in bytes.
71
71
  #
72
72
  # If the stat can't be acquired, this method will return nil.
73
- def used(fs = ?/.freeze)
73
+ def used(fs = ?..freeze)
74
74
  s = stat_raw(fs)
75
75
  return nil if s.empty?
76
76
  s.default = 0
@@ -78,7 +78,7 @@ module LinuxStat
78
78
  end
79
79
 
80
80
  ##
81
- # = available(fs = '/')
81
+ # = available(fs = '.')
82
82
  #
83
83
  # Where fs is the directory of the file system (like / or /tmp/ or /run/media/thumbdrive).
84
84
  #
@@ -89,7 +89,7 @@ module LinuxStat
89
89
  # Available returns the size of free blocks for unpriviledged users.
90
90
  #
91
91
  # If the stat can't be acquired, this method will return an empty Hash.
92
- def available(fs = ?/.freeze)
92
+ def available(fs = ?..freeze)
93
93
  s = stat_raw(fs)
94
94
  return nil if s.empty?
95
95
  s.default = 0
@@ -97,7 +97,7 @@ module LinuxStat
97
97
  end
98
98
 
99
99
  ##
100
- # = stat_raw(fs = '/')
100
+ # = stat_raw(fs = '.')
101
101
  #
102
102
  # Where fs is the directory of the file system (like / or /tmp/ or /run/media/thumbdrive).
103
103
  #
@@ -105,7 +105,7 @@ module LinuxStat
105
105
  # {:block_size=>4096, :fragment_size=>4096, :blocks=>29292283, :block_free=>10535967, :block_avail_unpriv=>10535967, :inodes=>58612160, :free_inodes=>56718550, :filesystem_id=>2050, :mount_flags=>1024, :max_filename_length=>255}
106
106
  #
107
107
  # If the stat can't be acquired, this method will return an empty Hash.
108
- def stat_raw(fs = ?/.freeze)
108
+ def stat_raw(fs = ?..freeze)
109
109
  LinuxStat::FS.stat(fs)
110
110
  end
111
111
  end
@@ -185,7 +185,7 @@ module LinuxStat
185
185
 
186
186
  private
187
187
  def splitted
188
- @@string_splitted ||= string.split
188
+ @@string_splitted ||= string.split.freeze
189
189
  end
190
190
  end
191
191
  end
@@ -121,7 +121,7 @@ module LinuxStat
121
121
  hour: h,
122
122
  minute: m,
123
123
  second: s
124
- }
124
+ }.freeze
125
125
  end
126
126
 
127
127
  private
@@ -143,7 +143,7 @@ module LinuxStat
143
143
  end
144
144
 
145
145
  def uptime_readable?
146
- @@uptime_readable = File.readable?('/proc/uptime')
146
+ @@uptime_readable ||= File.readable?('/proc/uptime')
147
147
  end
148
148
  end
149
149
  end
@@ -100,10 +100,7 @@ module LinuxStat
100
100
 
101
101
  private
102
102
  def pad_left(n, mantissa_length = 2)
103
- n = n.round(mantissa_length)
104
- exp, mant = n.to_s.split(?..freeze)
105
- m = mant.length < mantissa_length ? mant + ?0.freeze * (mantissa_length - mant.length) : mant
106
- exp + ?..freeze + m
103
+ sprintf("%.#{mantissa_length}f".freeze, n)
107
104
  end
108
105
  end
109
106
  end
@@ -6,7 +6,7 @@ module LinuxStat
6
6
  #
7
7
  # The return type is an Array of Integers.
8
8
  def list
9
- Dir['/proc/*'].select! { |x|
9
+ Dir['/proc/*'].select { |x|
10
10
  pid = File.split(x)[1]
11
11
  pid.to_i.to_s == pid
12
12
  }.map! { |x| File.split(x)[-1].to_i }
@@ -203,13 +203,13 @@ module LinuxStat
203
203
  end
204
204
 
205
205
  ##
206
- # = cpu_stat(pid: $$, sleep: 1.0 / LinuxStat::Sysconf.sc_clk_tck)
206
+ # = cpu_stat(pid: $$, sleep: 1.0 / LinuxStat::Sysconf.sc_clk_tck * 5)
207
207
  #
208
208
  # Where pid is the process ID and sleep time is the interval between measurements.
209
209
  #
210
210
  # By default it is the id of the current process ($$), and sleep is LinuxStat::Sysconf.sc_clk_tck
211
211
  #
212
- # The smallest amount of available sleep time is 1.0 / LinuxStat::Sysconf.sc_clk_tck.
212
+ # The smallest amount of available sleep time is 1.0 / LinuxStat::Sysconf.sc_clk_tck * 5.
213
213
  #
214
214
  # * Note 1:
215
215
  # 1. Do note that the sleep time can slow down your application.
@@ -244,20 +244,22 @@ module LinuxStat
244
244
  # Only use this method if you need all of the data at once, in such case, it's more efficient to use this method.
245
245
  #
246
246
  # The :last_executed_cpu also returns an Integer indicating the last executed cpu of the process.
247
- def cpu_stat(pid: $$, sleep: ticks_to_ms)
247
+ def cpu_stat(pid: $$, sleep: ticks_to_ms_t5)
248
248
  file = "/proc/#{pid}/stat"
249
- return {} unless File.readable?(file)
250
-
251
249
  ticks = get_ticks
252
250
 
251
+ return {} unless File.readable?(file)
253
252
  utime, stime, starttime = IO.read(file)
254
253
  .split.values_at(13, 14, 21).map(&:to_f)
254
+
255
255
  uptime = IO.read('/proc/uptime'.freeze).to_f * ticks
256
256
 
257
257
  total_time = utime + stime
258
258
  idle1 = uptime - starttime - total_time
259
259
 
260
260
  sleep(sleep)
261
+
262
+ return {} unless File.readable?(file)
261
263
  stat = IO.read(file).split
262
264
 
263
265
  utime2, stime2, starttime2 = stat.values_at(13, 14, 21).map(&:to_f)
@@ -267,25 +269,25 @@ module LinuxStat
267
269
  idle2 = uptime - starttime2 - total_time2
268
270
 
269
271
  totald = idle2.+(total_time2).-(idle1 + total_time)
270
- cpu = totald.-(idle2 - idle1).fdiv(totald).*(100).round(2).abs./(LinuxStat::CPU.count)
272
+ cpu_u = totald.-(idle2 - idle1).fdiv(totald).abs.*(100)./(cpu_count)
271
273
 
272
274
  {
273
- cpu_usage: cpu,
275
+ cpu_usage: cpu_u > 100 ? 100.0 : cpu_u.round(2),
274
276
  threads: stat[19].to_i,
275
277
  last_executed_cpu: stat[38].to_i
276
278
  }
277
279
  end
278
280
 
279
281
  ##
280
- # = cpu_usage(pid: $$, sleep: 1.0 / LinuxStat::Sysconf.sc_clk_tck)
282
+ # = cpu_usage(pid: $$, sleep: 1.0 / LinuxStat::Sysconf.sc_clk_tck * 5)
281
283
  #
282
284
  # Where pid is the process ID and sleep time is the interval between measurements.
283
285
  #
284
- # By default it is the id of the current process ($$), and sleep is 1.0 / LinuxStat::Sysconf.sc_clk_tck
286
+ # By default it is the id of the current process ($$), and sleep is 1.0 / LinuxStat::Sysconf.sc_clk_tck * 5
285
287
  #
286
288
  # The smallest amount of available sleep time is LinuxStat::Sysconf.sc_clk_tck.
287
289
  #
288
- # It retuns the CPU usage in Float.
290
+ # It retuns the CPU usage as Float.
289
291
  #
290
292
  # For example:
291
293
  #
@@ -293,19 +295,75 @@ module LinuxStat
293
295
  #
294
296
  # => 10.0
295
297
  #
298
+ # 10.0 means it's using 10% of the total processing power of the system.
299
+ #
300
+ # The value is divided with the configured number of CPU and not online CPU.
301
+ #
296
302
  # A value of 100.0 indicates it is using 100% processing power available to the system.
297
303
  #
298
304
  # But if the info isn't available, it will return nil.
299
305
  #
300
306
  # This method is more efficient than running LinuxStat::ProcessInfo.cpu_stat()
301
- def cpu_usage(pid: $$, sleep: ticks_to_ms)
307
+ def cpu_usage(pid: $$, sleep: ticks_to_ms_t5)
302
308
  file = "/proc/#{pid}/stat"
309
+ ticks = get_ticks
310
+
311
+ return nil unless File.readable?(file)
312
+ utime, stime, starttime = IO.read(file)
313
+ .split.values_at(13, 14, 21).map(&:to_f)
314
+
315
+ uptime = IO.read('/proc/uptime'.freeze).to_f * ticks
316
+
317
+ total_time = utime + stime
318
+ idle1 = uptime - starttime - total_time
319
+
320
+ sleep(sleep)
321
+
303
322
  return nil unless File.readable?(file)
323
+ utime2, stime2, starttime2 = IO.read(file)
324
+ .split.values_at(13, 14, 21).map(&:to_f)
325
+
326
+ uptime = IO.read('/proc/uptime'.freeze).to_f * ticks
327
+
328
+ total_time2 = utime2 + stime2
329
+ idle2 = uptime - starttime2 - total_time2
330
+
331
+ totald = idle2.+(total_time2).-(idle1 + total_time)
304
332
 
333
+ u = totald.-(idle2 - idle1).fdiv(totald).abs.*(100)./(cpu_count)
334
+ u > 100 ? 100.0 : u.round(2)
335
+ end
336
+
337
+ ##
338
+ # = thread_usage(pid: $$, sleep: 1.0 / LinuxStat::Sysconf.sc_clk_tck * 5)
339
+ #
340
+ # Where pid is the process ID and sleep time is the interval between measurements.
341
+ #
342
+ # By default it is the id of the current process ($$), and sleep is 1.0 / LinuxStat::Sysconf.sc_clk_tck * 5
343
+ #
344
+ # The smallest amount of available sleep time is LinuxStat::Sysconf.sc_clk_tck.
345
+ #
346
+ # It retuns the per core CPU usage as Float.
347
+ #
348
+ # For example:
349
+ #
350
+ # LinuxStat::ProcessInfo.core_usage
351
+ #
352
+ # => 200.0
353
+ #
354
+ # A value of 100.0 indicates it is using 100% processing power of a core.
355
+ #
356
+ # The value could be 0 to (100 * the number of CPU threads (including hyperthreading) in the system)
357
+ #
358
+ # But if the info isn't available, it will return nil.
359
+ def thread_usage(pid: $$, sleep: ticks_to_ms_t5)
360
+ file = "/proc/#{pid}/stat"
305
361
  ticks = get_ticks
306
362
 
363
+ return nil unless File.readable?(file)
307
364
  utime, stime, starttime = IO.read(file)
308
365
  .split.values_at(13, 14, 21).map(&:to_f)
366
+
309
367
  uptime = IO.read('/proc/uptime'.freeze).to_f * ticks
310
368
 
311
369
  total_time = utime + stime
@@ -313,15 +371,21 @@ module LinuxStat
313
371
 
314
372
  sleep(sleep)
315
373
 
374
+ return nil unless File.readable?(file)
316
375
  utime2, stime2, starttime2 = IO.read(file)
317
376
  .split.values_at(13, 14, 21).map(&:to_f)
377
+
318
378
  uptime = IO.read('/proc/uptime'.freeze).to_f * ticks
319
379
 
320
380
  total_time2 = utime2 + stime2
321
381
  idle2 = uptime - starttime2 - total_time2
322
382
 
323
383
  totald = idle2.+(total_time2).-(idle1 + total_time)
324
- totald.-(idle2 - idle1).fdiv(totald).*(100).round(2).abs./(LinuxStat::CPU.count)
384
+
385
+ u = totald.-(idle2 - idle1).fdiv(totald).abs.*(100)
386
+
387
+ cpu_count_t100 = cpu_count * 100
388
+ u > cpu_count_t100 ? cpu_count_t100 : u.round(2)
325
389
  end
326
390
 
327
391
  ##
@@ -435,6 +499,32 @@ module LinuxStat
435
499
  LinuxStat::User.username_by_gid(gid)
436
500
  end
437
501
 
502
+ ##
503
+ # = start_time_epoch(pid = $$)
504
+ #
505
+ # Returns the epoch time (as Integer) the process was started.
506
+ #
507
+ # For example:
508
+ # LinuxStat::ProcessInfo.start_time_epoch 526
509
+ #
510
+ # => 1608097744
511
+ #
512
+ # If the info isn't available or the argument passed doesn't exist as a process ID, it will return nil.
513
+ def start_time_epoch(pid = $$)
514
+ stat_file = "/proc/#{pid}/stat".freeze
515
+ uptime = "/proc/uptime".freeze
516
+
517
+ @@u_readable ||= File.readable?(uptime)
518
+ return nil unless @@u_readable && File.readable?(stat_file)
519
+
520
+ u = IO.foreach(uptime, ' '.freeze).next.to_f
521
+ st = (IO.foreach(stat_file, ' '.freeze).first(22)[-1].to_f / get_ticks)
522
+
523
+ # Getting two Time objects and dealing with floating point numbers
524
+ # Just to make sure the time goes monotonically
525
+ Time.now.-(u - st).to_i
526
+ end
527
+
438
528
  ##
439
529
  # = start_time(pid = $$)
440
530
  #
@@ -443,7 +533,7 @@ module LinuxStat
443
533
  # For example:
444
534
  # LinuxStat::ProcessInfo.start_time 14183
445
535
  #
446
- # => 2020-12-16 13:31:43.559061275 +0000
536
+ # => 2020-12-16 13:31:43 +0000
447
537
  #
448
538
  # If the info isn't available or the argument passed doesn't exist as a process ID, it will return nil.
449
539
  #
@@ -452,13 +542,9 @@ module LinuxStat
452
542
  #
453
543
  # Don't trust the timezone returned by the time.
454
544
  def start_time(pid = $$)
455
- stat_file = "/proc/#{pid}/stat".freeze
456
- uptime = "/proc/uptime".freeze
457
-
458
- @@u_readable ||= File.readable?(uptime)
459
- return nil unless @@u_readable && File.readable?(stat_file)
460
-
461
- Time.now.-(IO.foreach(uptime, ' '.freeze).next.to_i - (IO.read(stat_file).split[21].to_i / get_ticks))
545
+ # Getting two Time objects and dealing with floating point numbers
546
+ # Just to make sure the time goes monotonically
547
+ Time.at(start_time_epoch(pid))
462
548
  end
463
549
 
464
550
  ##
@@ -469,7 +555,9 @@ module LinuxStat
469
555
  # For example:
470
556
  # LinuxStat::ProcessInfo.running_time 14183
471
557
  #
472
- # => 1947.619999999999
558
+ # => 1947.61
559
+ #
560
+ # It always rounds the float number upto 2 decimal places
473
561
  #
474
562
  # If the info isn't available or the argument passed doesn't exist as a process ID, it will return nil.
475
563
  def running_time(pid = $$)
@@ -479,7 +567,8 @@ module LinuxStat
479
567
  @@u_readable ||= File.readable?(uptime)
480
568
  return nil unless @@u_readable && File.readable?(stat_file)
481
569
 
482
- IO.foreach(uptime, ' '.freeze).next.to_f - (IO.read(stat_file).split[21].to_i / get_ticks)
570
+ IO.foreach(uptime, ' '.freeze).next.to_f
571
+ .-(IO.read(stat_file).split[21].to_f / get_ticks).round(2)
483
572
  end
484
573
 
485
574
  ##
@@ -522,19 +611,57 @@ module LinuxStat
522
611
  IO.foreach(file, ' ').first(19)[-1].to_i
523
612
  end
524
613
 
614
+ ##
615
+ # = nproc(pid = $$)
616
+ # Returns the cpu allocated to the process.
617
+ #
618
+ # The output value is an Integer.
619
+ #
620
+ # For example:
621
+ # $ taskset -c 0 irb
622
+ #
623
+ # irb(main):001:0> require 'linux_stat'
624
+ #
625
+ # => true
626
+ #
627
+ # irb(main):002:0> LinuxStat::ProcessInfo.nproc
628
+ #
629
+ # => 1
630
+ #
631
+ # irb(main):003:0> LinuxStat::ProcessInfo.nproc 11562
632
+ #
633
+ # => 3
634
+ #
635
+ # irb(main):004:0> LinuxStat::ProcessInfo.nproc 12513
636
+ #
637
+ # => 4
638
+ #
639
+ # If the info isn't available or the argument passed doesn't exist as a process ID, it will return nil.
640
+ def nproc(pid = $$)
641
+ LinuxStat::Nproc.count_cpu_for_pid(pid)
642
+ end
643
+
644
+ alias count_cpu nproc
645
+
525
646
  private
526
647
  def get_ticks
527
648
  @@ticks ||= Sysconf.sc_clk_tck
528
649
  end
529
650
 
530
651
  # Just to avoid multiple calculations!...
531
- def ticks_to_ms
532
- @@ms ||= 1.0 / get_ticks
652
+ # ticks to ms * 5
653
+ # If ticks is 100, it will return 0.05
654
+ def ticks_to_ms_t5
655
+ @@ms_t5 ||= 1.0 / get_ticks * 5
533
656
  end
534
657
 
535
658
  def pagesize
536
659
  @@pagesize ||= LinuxStat::Sysconf.pagesize
537
660
  end
661
+
662
+ def cpu_count
663
+ @@nprocessors_conf ||= LinuxStat::CPU.count
664
+ end
538
665
  end
539
666
  end
540
667
  end