linux_stat 1.6.0 → 2.0.1

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.
data/bin/console CHANGED
@@ -1,4 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
2
  $-v = true
3
- %w(linux_stat irb).each(&method(:require))
3
+
4
+ begin
5
+ %w(linux_stat irb).each(&method(:require))
6
+ rescue LoadError
7
+ abort "LinuxStat and IRB shoud be installed before you can run LinuxStat console"
8
+ end
9
+
4
10
  IRB.start(__FILE__)
data/exe/linuxstat.rb CHANGED
@@ -7,6 +7,12 @@ rescue LoadError
7
7
  abort "The Gem needs to be installed before this test can be run!"
8
8
  end
9
9
 
10
+ Integer.class_exec do
11
+ define_method(:clamp) { |min, max|
12
+ self < min ? min : self > max ? max : self
13
+ }
14
+ end unless 1.respond_to?(:clamp)
15
+
10
16
  # Gradient colour to strings
11
17
  class String
12
18
  def colourize(colour = 1, flip: false)
@@ -0,0 +1,11 @@
1
+ require 'mkmf'
2
+
3
+ unless have_const('linux') || RbConfig::CONFIG['arch'].to_s[/linux/]
4
+ abort('Platform is not linux')
5
+ end
6
+
7
+ unless have_header('unistd.h') && have_header('ruby.h')
8
+ abort('Missing header')
9
+ end
10
+
11
+ create_makefile 'linux_stat/procfs'
@@ -0,0 +1,11 @@
1
+ VALUE last_pid(VALUE obj) {
2
+ FILE *f = fopen("/proc/loadavg", "r") ;
3
+ if (!f) return Qnil ;
4
+
5
+ unsigned long long _last_pid ;
6
+ char status = fscanf(f, "%*f %*f %*f %*s %llu", &_last_pid) ;
7
+ fclose(f) ;
8
+ if (status != 1) return Qnil ;
9
+
10
+ return ULL2NUM(_last_pid) ;
11
+ }
@@ -0,0 +1,42 @@
1
+ // ProcFS doesn't include all the /proc/ files.
2
+ // It includes some of them that can add potential
3
+ // performance boost to the LinuxStat modules.
4
+ //
5
+ // Some LinuxStat modules reads /proc/ files
6
+ // that are not present here. That is because
7
+ // Ruby can handle them well with little wastage.
8
+ // Adding C may be a potential risk in such places.
9
+ //
10
+ // In this ProcFS module, we will define the methods
11
+ // that really gets the benefit.
12
+
13
+ #include <stdio.h>
14
+ #include <unistd.h>
15
+ #include <string.h>
16
+ #include "ruby.h"
17
+ #include "uptime.h"
18
+ #include "statm.h"
19
+ #include "stat.h"
20
+ #include "loadavg_pid.h"
21
+
22
+ int Init_procfs() {
23
+ VALUE _linux_stat = rb_define_module("LinuxStat") ;
24
+ VALUE _procfs = rb_define_module_under(_linux_stat, "ProcFS") ;
25
+
26
+ // uptime
27
+ rb_define_module_function(_procfs, "uptime_f", uptime_f, 0) ;
28
+
29
+ // statm
30
+ rb_define_module_function(_procfs, "statm_memory", statm_memory, 1) ;
31
+ rb_define_module_function(_procfs, "statm", statm, 1) ;
32
+ rb_define_module_function(_procfs, "statm_virtual", statm_virtual, 1) ;
33
+ rb_define_module_function(_procfs, "statm_resident", statm_resident, 1) ;
34
+ rb_define_module_function(_procfs, "statm_shared", statm_shared, 1) ;
35
+
36
+ // loadavg last PID
37
+ rb_define_module_function(_procfs, "last_pid", last_pid, 0) ;
38
+
39
+ // stat
40
+ rb_define_module_function(_procfs, "ps_state", ps_state, 1) ;
41
+ rb_define_module_function(_procfs, "ps_stat", ps_stat, 1) ;
42
+ }
data/ext/procfs/stat.h ADDED
@@ -0,0 +1,92 @@
1
+ VALUE ps_state(VALUE obj, VALUE pid) {
2
+ char _path[22] ;
3
+ sprintf(_path, "/proc/%lu/stat", FIX2UINT(pid)) ;
4
+
5
+ FILE *f = fopen(_path, "r") ;
6
+ if (!f) return rb_str_new_cstr("") ;
7
+
8
+ char _s[1] ;
9
+
10
+ char status = fscanf(f, "%*llu (%*[^)]%*[)] %s", _s) ;
11
+ fclose(f) ;
12
+
13
+ if (status != 1) return rb_str_new_cstr("") ;
14
+ return rb_str_new_cstr(_s) ;
15
+ }
16
+
17
+ VALUE ps_stat(VALUE obj, VALUE pid) {
18
+ char _path[22] ;
19
+ sprintf(_path, "/proc/%lu/stat", FIX2UINT(pid)) ;
20
+
21
+ FILE *f = fopen(_path, "r") ;
22
+
23
+ if (!f)
24
+ return rb_ary_new() ;
25
+
26
+ // ?? JEEZ !!
27
+ // We need to do this because the datatypes are different
28
+ // Can't make an array like Ruby out of String
29
+ // This is hard to write and check, but tested, and works.
30
+ //
31
+ // For this struct,
32
+ // follow https://man7.org/linux/man-pages/man5/proc.5.html
33
+ int ppid, pgrp, session, tty_nr, tpgid ;
34
+ unsigned flags ;
35
+ long unsigned minflt, cminflt, majflt, cmajflt, utime, stime ;
36
+ long cutime, cstime, priority, nice, num_threads, itrealvalue ;
37
+ long long unsigned starttime ;
38
+ long unsigned vsize ;
39
+ long rss ;
40
+ long unsigned rsslim, startcode, endcode, startstack, kstkesp, kstkeip ;
41
+ long unsigned signal, blocked, sigignore, sigcatch, wchan, nswap, cnswap ;
42
+ int exit_signal, processor ;
43
+ unsigned rt_priority, policy ;
44
+ long long unsigned delayacct_blkio_ticks ;
45
+ long unsigned guest_time ;
46
+ long cguest_time ;
47
+ long unsigned start_data, end_data, start_brk, arg_start, arg_end ;
48
+ long unsigned env_start, env_end ;
49
+ int exit_code ;
50
+
51
+ char status = fscanf(
52
+ f, "%*llu (%*[^)]%*[)] %*c "
53
+ "%d %d %d %d %d %u "
54
+ "%lu %lu %lu %lu %lu %lu "
55
+ "%ld %ld %ld %ld %ld %ld "
56
+ "%llu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu "
57
+ "%d %d %u %u %llu %lu %ld %lu %lu %lu %lu %lu %lu %lu %d", &ppid, &pgrp,
58
+ &session, &tty_nr, &tpgid, &flags, &minflt, &cminflt, &majflt, &cmajflt, &utime, &stime, &cutime,
59
+ &cstime, &priority, &nice, &num_threads, &itrealvalue, &starttime, &vsize, &rss, &rsslim,
60
+ &startcode, &endcode, &startstack, &kstkesp, &kstkeip, &signal, &blocked, &sigignore,
61
+ &sigcatch, &wchan, &nswap, &cnswap, &exit_signal, &processor, &rt_priority, &policy,
62
+ &delayacct_blkio_ticks, &guest_time, &cguest_time, &start_data, &end_data,
63
+ &start_brk, &arg_start, &arg_end, &env_start, &env_end, &exit_code
64
+ ) ;
65
+
66
+ fclose(f) ;
67
+
68
+ if (status != 49)
69
+ return rb_ary_new() ;
70
+
71
+ return rb_ary_new_from_args(49,
72
+ INT2NUM(ppid), INT2NUM(pgrp), INT2NUM(session), INT2NUM(tty_nr), INT2NUM(tpgid),
73
+ UINT2NUM(flags),
74
+ ULONG2NUM(minflt), ULONG2NUM(cminflt), ULONG2NUM(majflt), ULONG2NUM(cmajflt),
75
+ ULONG2NUM(utime), ULONG2NUM(stime),
76
+ LONG2NUM(cutime), LONG2NUM(cstime), LONG2NUM(priority),
77
+ LONG2NUM(nice), LONG2NUM(num_threads), LONG2NUM(itrealvalue),
78
+ ULL2NUM(starttime),
79
+ ULONG2NUM(vsize),
80
+ LONG2NUM(rss),
81
+ ULONG2NUM(rsslim), ULONG2NUM(startcode), ULONG2NUM(endcode),
82
+ ULONG2NUM(startstack), ULONG2NUM(kstkesp), ULONG2NUM(kstkeip),
83
+ ULONG2NUM(signal), ULONG2NUM(blocked), ULONG2NUM(sigignore), ULONG2NUM(sigcatch),
84
+ ULONG2NUM(wchan), ULONG2NUM(nswap), ULONG2NUM(cnswap),
85
+ INT2NUM(exit_signal), INT2NUM(processor),
86
+ UINT2NUM(rt_priority), UINT2NUM(policy),
87
+ ULL2NUM(delayacct_blkio_ticks), ULONG2NUM(guest_time), LONG2NUM(cguest_time), ULONG2NUM(start_data),
88
+ ULONG2NUM(end_data), ULONG2NUM(start_brk), ULONG2NUM(arg_start), ULONG2NUM(arg_end),
89
+ ULONG2NUM(env_start), ULONG2NUM(env_end),
90
+ INT2NUM(exit_code)
91
+ ) ;
92
+ }
@@ -0,0 +1,99 @@
1
+ #define PAGESIZE sysconf(_SC_PAGESIZE)
2
+
3
+ VALUE statm(VALUE obj, VALUE pid) {
4
+ char _path[22] ;
5
+ sprintf(_path, "/proc/%lu/statm", FIX2UINT(pid)) ;
6
+
7
+ FILE *f = fopen(_path, "r") ;
8
+
9
+ VALUE hash = rb_hash_new() ;
10
+
11
+ if (!f) return hash ;
12
+
13
+ unsigned int _virtual, resident, shared ;
14
+ char status = fscanf(f, "%u %u %u", &_virtual, &resident, &shared) ;
15
+ fclose(f) ;
16
+
17
+ if (status != 3) return hash ;
18
+
19
+ int pagesize = PAGESIZE ;
20
+
21
+ _virtual *= pagesize ;
22
+ resident *= pagesize ;
23
+ shared *= pagesize ;
24
+
25
+ unsigned int v = resident - shared ;
26
+
27
+ rb_hash_aset(hash, ID2SYM(rb_intern("memory")), UINT2NUM(v)) ;
28
+ rb_hash_aset(hash, ID2SYM(rb_intern("virtual_memory")), UINT2NUM(_virtual)) ;
29
+ rb_hash_aset(hash, ID2SYM(rb_intern("resident_memory")), UINT2NUM(resident)) ;
30
+ rb_hash_aset(hash, ID2SYM(rb_intern("shared_memory")), UINT2NUM(shared)) ;
31
+
32
+ return hash ;
33
+ }
34
+
35
+ VALUE statm_virtual(VALUE obj, VALUE pid) {
36
+ char _path[22] ;
37
+ sprintf(_path, "/proc/%lu/statm", FIX2UINT(pid)) ;
38
+
39
+ FILE *f = fopen(_path, "r") ;
40
+ VALUE hash = rb_hash_new() ;
41
+
42
+ if (!f) return hash ;
43
+ unsigned int _virtual ;
44
+ char status = fscanf(f, "%u", &_virtual) ;
45
+ fclose(f) ;
46
+
47
+ if (status != 1) return Qnil ;
48
+ return UINT2NUM(_virtual * PAGESIZE) ;
49
+ }
50
+
51
+ VALUE statm_resident(VALUE obj, VALUE pid) {
52
+ char _path[22] ;
53
+ sprintf(_path, "/proc/%lu/statm", FIX2UINT(pid)) ;
54
+
55
+ FILE *f = fopen(_path, "r") ;
56
+ VALUE hash = rb_hash_new() ;
57
+
58
+ if (!f) return hash ;
59
+ unsigned int resident ;
60
+ char status = fscanf(f, "%*u %u", &resident) ;
61
+ fclose(f) ;
62
+
63
+ if (status != 1) return Qnil ;
64
+ return UINT2NUM(resident * PAGESIZE) ;
65
+ }
66
+
67
+ VALUE statm_shared(VALUE obj, VALUE pid) {
68
+ char _path[22] ;
69
+ sprintf(_path, "/proc/%lu/statm", FIX2UINT(pid)) ;
70
+
71
+ FILE *f = fopen(_path, "r") ;
72
+ VALUE hash = rb_hash_new() ;
73
+
74
+ if (!f) return hash ;
75
+ unsigned int shared ;
76
+ char status = fscanf(f, "%*u %*u %u", &shared) ;
77
+ fclose(f) ;
78
+
79
+ if (status != 1) return Qnil ;
80
+ return UINT2NUM(shared * PAGESIZE) ;
81
+ }
82
+
83
+ VALUE statm_memory(VALUE obj, VALUE pid) {
84
+ char _path[22] ;
85
+ sprintf(_path, "/proc/%lu/statm", FIX2UINT(pid)) ;
86
+
87
+ FILE *f = fopen(_path, "r") ;
88
+
89
+ if (!f) return Qnil ;
90
+
91
+ unsigned int resident, shared ;
92
+ char status = fscanf(f, "%*u %u %u", &resident, &shared) ;
93
+ fclose(f) ;
94
+
95
+ if (status != 2) return Qnil ;
96
+
97
+ unsigned int v = (resident - shared) * PAGESIZE ;
98
+ return UINT2NUM(v) ;
99
+ }
@@ -0,0 +1,12 @@
1
+ VALUE uptime_f(VALUE obj) {
2
+ FILE *f = fopen("/proc/uptime", "r") ;
3
+ if (!f) return Qnil ;
4
+
5
+ double up_f ;
6
+ char status = fscanf(f, "%lf", &up_f) ;
7
+ fclose(f) ;
8
+
9
+ if (status != 1) return Qnil ;
10
+
11
+ return DBL2NUM(up_f) ;
12
+ }
data/lib/linux_stat.rb CHANGED
@@ -25,13 +25,16 @@ require "linux_stat/battery"
25
25
  require "linux_stat/bios"
26
26
  require "linux_stat/net"
27
27
  require "linux_stat/pci"
28
- require "linux_stat/process"
29
28
  require "linux_stat/thermal"
30
29
  require "linux_stat/usb"
31
30
 
32
31
  # Dependent Modules
33
32
  # Modules that can have reverse dependency
34
33
 
34
+ # LinuxStat::ProcFS dependent modules
35
+ require "linux_stat/procfs"
36
+ require "linux_stat/process"
37
+
35
38
  # LinuxStat::CPU.sysinfo dependent modules
36
39
  require "linux_stat/sysinfo"
37
40
  require "linux_stat/swap"
@@ -30,7 +30,7 @@ module LinuxStat
30
30
  data = IO.readlines(DEV).drop(2)
31
31
  indices = find_index_of_bytes
32
32
  data.reject! { |x| x.strip.start_with?('lo:') }
33
- r, t = data.map { |x| x.split.values_at(*indices).map(&:to_i) }.transpose.map(&:sum)
33
+ r, t = data.map { |x| x.split.values_at(*indices).map(&:to_i) }.transpose.map { |x| x.reduce(:+) }
34
34
 
35
35
  {
36
36
  received: r,
@@ -48,7 +48,7 @@ module LinuxStat
48
48
  data = IO.readlines(DEV).drop(2)
49
49
  index = find_index_of_bytes[0]
50
50
  data.reject! { |x| x.strip.start_with?('lo:') }
51
- data.map { |x| x.split[index].to_i }.sum
51
+ data.map { |x| x.split[index].to_i }.reduce(:+)
52
52
  end
53
53
 
54
54
  ##
@@ -61,7 +61,7 @@ module LinuxStat
61
61
  data = IO.readlines(DEV).drop(2)
62
62
  index = find_index_of_bytes[-1]
63
63
  data.reject! { |x| x.strip.start_with?('lo:') }
64
- data.map { |x| x.split[index].to_i }.sum
64
+ data.map { |x| x.split[index].to_i }.reduce(:+)
65
65
  end
66
66
 
67
67
  ##
@@ -89,13 +89,13 @@ module LinuxStat
89
89
  data = IO.readlines(DEV).drop(2)
90
90
  indices = find_index_of_bytes
91
91
  data.reject! { |x| x.strip.start_with?('lo:'.freeze) }
92
- r, t = data.map { |x| x.split.values_at(*indices).map(&:to_i) }.transpose.map(&:sum)
92
+ r, t = data.map { |x| x.split.values_at(*indices).map(&:to_i) }.transpose.map { |x| x.reduce(:+) }
93
93
 
94
94
  sleep(interval)
95
95
 
96
96
  data2 = IO.readlines(DEV).drop(2)
97
97
  data2.reject! { |x| x.strip.start_with?('lo:'.freeze) }
98
- r2, t2 = data2.map { |x| x.split.values_at(*indices).map(&:to_i) }.transpose.map(&:sum)
98
+ r2, t2 = data2.map { |x| x.split.values_at(*indices).map(&:to_i) }.transpose.map { |x| x.reduce(:+) }
99
99
 
100
100
  # Measure the difference
101
101
  dr, dt = r2.-(r).fdiv(interval), t2.-(t).fdiv(interval)
data/lib/linux_stat/os.rb CHANGED
@@ -144,20 +144,20 @@ module LinuxStat
144
144
  #
145
145
  # If the stat isn't available, an empty hash is returned.
146
146
  def uptime
147
- return {} unless uptime_readable?
147
+ _uptime = LinuxStat::ProcFS.uptime_f
148
+ return {} unless _uptime
148
149
 
149
- uptime = IO.read('/proc/uptime'.freeze).to_f
150
- uptime_i = uptime.to_i
150
+ uptime_i = _uptime.to_i
151
151
 
152
152
  h = uptime_i / 3600
153
153
  m = uptime_i % 3600 / 60
154
- s = uptime.%(3600).%(60).round(2)
154
+ s = _uptime.%(3600).%(60).round(2)
155
155
 
156
156
  {
157
157
  hour: h,
158
158
  minute: m,
159
159
  second: s
160
- }.freeze
160
+ }
161
161
  end
162
162
 
163
163
  ##
@@ -172,8 +172,7 @@ module LinuxStat
172
172
  #
173
173
  # If the stat isn't available, nil is returned.
174
174
  def uptime_f
175
- return nil unless uptime_readable?
176
- IO.foreach('/proc/uptime'.freeze, ' ').next.to_f
175
+ LinuxStat::ProcFS.uptime_f
177
176
  end
178
177
 
179
178
  ##
@@ -232,10 +231,6 @@ module LinuxStat
232
231
  h.merge!( key.to_sym => value )
233
232
  }
234
233
  end
235
-
236
- def uptime_readable?
237
- @@uptime_readable ||= File.readable?('/proc/uptime')
238
- end
239
234
  end
240
235
  end
241
236
  end
@@ -86,7 +86,7 @@ module LinuxStat
86
86
 
87
87
  begin
88
88
  h.merge!(x =>
89
- case IO.read("/proc/#{x}/stat").split(/(\(.*\))/)[-1][/\s.+?/].strip
89
+ case LinuxStat::ProcFS.ps_state(x)
90
90
  when ?S.freeze then :sleeping
91
91
  when ?I.freeze then :idle
92
92
  when ?Z.freeze then :zombie
@@ -110,11 +110,7 @@ module LinuxStat
110
110
  # The return type is an Array of Integers.
111
111
  def sleeping
112
112
  list.select { |x|
113
- begin
114
- IO.read("/proc/#{x}/stat").split(/(\(.*\))/)[-1][/\s.+?/].strip == ?S.freeze
115
- rescue StandardError
116
- false
117
- end
113
+ LinuxStat::ProcFS.ps_state(x) == ?S.freeze
118
114
  }
119
115
  end
120
116
 
@@ -123,11 +119,7 @@ module LinuxStat
123
119
  # The return type is an Array of Integers.
124
120
  def idle
125
121
  list.select { |x|
126
- begin
127
- IO.read("/proc/#{x}/stat").split(/(\(.*\))/)[-1][/\s.+?/].strip == ?I.freeze
128
- rescue StandardError
129
- false
130
- end
122
+ LinuxStat::ProcFS.ps_state(x) == ?I.freeze
131
123
  }
132
124
  end
133
125
 
@@ -136,11 +128,7 @@ module LinuxStat
136
128
  # The return type is an Array of Integers.
137
129
  def zombie
138
130
  list.select { |x|
139
- begin
140
- IO.read("/proc/#{x}/stat").split(/(\(.*\))/)[-1][/\s.+?/].strip == ?Z.freeze
141
- rescue StandardError
142
- false
143
- end
131
+ LinuxStat::ProcFS.ps_state(x) == ?Z.freeze
144
132
  }
145
133
  end
146
134
 
@@ -149,11 +137,7 @@ module LinuxStat
149
137
  # The return type is an Array of Integers.
150
138
  def running
151
139
  list.select { |x|
152
- begin
153
- IO.read("/proc/#{x}/stat").split(/(\(.*\))/)[-1][/\s.+?/].strip == ?R.freeze
154
- rescue StandardError
155
- false
156
- end
140
+ LinuxStat::ProcFS.ps_state(x) == ?R.freeze
157
141
  }
158
142
  end
159
143
 
@@ -162,14 +146,20 @@ module LinuxStat
162
146
  # The return type is an Array of Integers.
163
147
  def stopped
164
148
  list.select { |x|
165
- begin
166
- v = IO.read("/proc/#{x}/stat").split(/(\(.*\))/)[-1][/\s.+?/].strip
167
- v == ?T.freeze || v == ?t.freeze
168
- rescue StandardError
169
- false
170
- end
149
+ v = LinuxStat::ProcFS.ps_state(x)
150
+ v == ?T.freeze || v == ?t.freeze
171
151
  }
172
152
  end
153
+
154
+ ##
155
+ # Returns the last_pid of the system.
156
+ # It directly calls LS::ProcFS.last_pid
157
+ #
158
+ # The return value is Integer, but if the status
159
+ # isn't available, it will return nil
160
+ def last_pid
161
+ LinuxStat::ProcFS.last_pid
162
+ end
173
163
  end
174
164
  end
175
165
  end