linux_stat 2.3.0 → 2.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +41 -8
- data/exe/linuxstat.rb +7 -7
- data/ext/misc/integer/extconf.rb +2 -0
- data/ext/misc/integer/integer?.c +63 -0
- data/ext/procfs/procfs.c +6 -0
- data/ext/procfs/stat.h +66 -0
- data/lib/linux_stat/battery.rb +1 -1
- data/lib/linux_stat/cpu.rb +123 -12
- data/lib/linux_stat/mounts.rb +3 -3
- data/lib/linux_stat/net.rb +2 -2
- data/lib/linux_stat/os.rb +2 -1
- data/lib/linux_stat/pci.rb +9 -9
- data/lib/linux_stat/process.rb +14 -24
- data/lib/linux_stat/process_info.rb +1 -1
- data/lib/linux_stat/swap.rb +2 -1
- data/lib/linux_stat/thermal.rb +4 -4
- data/lib/linux_stat/usb.rb +10 -10
- data/lib/linux_stat/user.rb +10 -4
- data/lib/linux_stat/version.rb +1 -1
- data/lib/linux_stat.rb +1 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c9155ed8b1f6161a8bafcb9fbd9f1a1d9f70b018ca62aabf49ad1c7439030ee2
|
4
|
+
data.tar.gz: 22e52732cd8c8a2fca1f34ca9ece06178373c800ddbc200c42d1a61d49c29995
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d1f781908039e1946676f8a1502321b530538aef6d303976b07930c6d8933e7a45ca671e1aa3438fc774caa68c1b939f1ee12f47a5a6399523700b46cfb0c9f5
|
7
|
+
data.tar.gz: cd51272b3c145c9a57a5b3ae444c21119430106436e29c843420269cbad47044fdc4e3836bf86e61404c6df20f462164dc673ec5e6d76b4acacfcc37effc61c8
|
data/README.md
CHANGED
@@ -38,18 +38,36 @@ It only works on Linux, and detecting the OS is upto the user of this gem.
|
|
38
38
|
2. Ruby: Ruby 2.3.0 and above.
|
39
39
|
|
40
40
|
## Build Dependencies:
|
41
|
-
|
42
|
-
|
41
|
+
#### You need to have the C compiler installed to be able to compile the C extensions.
|
42
|
+
|
43
|
+
+ On Arch Linux / Manjaro / Archlabs / Other Arch Based Distributions
|
44
|
+
```
|
45
|
+
# pacman -S gcc make ruby
|
46
|
+
```
|
47
|
+
|
48
|
+
+ On Debian / Ubuntu / Linux Mint / Pop!_OS / Raspberry Pi OS / Other Debian Based Distributions
|
49
|
+
```
|
50
|
+
# apt install gcc build-essential ruby ruby-dev build-essential
|
51
|
+
```
|
52
|
+
|
53
|
+
+ Gentoo / Gentoo Based Distributions
|
54
|
+
```
|
55
|
+
# emerge --ask dev-lang/ruby
|
56
|
+
```
|
57
|
+
|
58
|
+
+ Fedora / AmazonLinux* / CentOS* / Other RedHat Based Distributions
|
43
59
|
```
|
44
|
-
#
|
60
|
+
# yum install gcc ruby-devel ruby make
|
45
61
|
```
|
46
62
|
|
47
|
-
|
63
|
+
You can run linux_stat on *AmazonLinux and *CentOS if you have Ruby 2.3.0+.
|
64
|
+
|
65
|
+
+ OpenSUSE
|
48
66
|
```
|
49
|
-
#
|
67
|
+
# zypper install gcc ruby ruby-devel make
|
50
68
|
```
|
51
69
|
|
52
|
-
+ You can remove the packages once the
|
70
|
+
+ You can remove the above packages once the gem is installed.
|
53
71
|
|
54
72
|
---
|
55
73
|
|
@@ -62,13 +80,28 @@ You can install hwdata simply.
|
|
62
80
|
+ Arch:
|
63
81
|
|
64
82
|
```
|
65
|
-
|
83
|
+
# pacman -S hwids
|
66
84
|
```
|
67
85
|
|
68
86
|
+ Debian based systems:
|
69
87
|
|
70
88
|
```
|
71
|
-
|
89
|
+
# apt install hwdata
|
90
|
+
```
|
91
|
+
|
92
|
+
+ Gentoo / Gentoo Based Distributions
|
93
|
+
```
|
94
|
+
# emerge --ask sys-apps/hwids
|
95
|
+
```
|
96
|
+
|
97
|
+
+ Fedora / Amazon Linux / CentOS
|
98
|
+
```
|
99
|
+
# yum install hwdata
|
100
|
+
```
|
101
|
+
|
102
|
+
+ OpenSUSE
|
103
|
+
```
|
104
|
+
zypper install hwdata
|
72
105
|
```
|
73
106
|
|
74
107
|
But without hwdata, it won't show such information.
|
data/exe/linuxstat.rb
CHANGED
@@ -11,7 +11,7 @@ end
|
|
11
11
|
T_FMT = '%d'.freeze
|
12
12
|
|
13
13
|
# Check the number of iterations
|
14
|
-
iterations = (ARGV.find { |x|
|
14
|
+
iterations = (ARGV.find { |x| LinuxStat::Misc.integer?(x) } || 1).to_i
|
15
15
|
|
16
16
|
Integer.class_exec do
|
17
17
|
define_method(:clamp) { |min, max|
|
@@ -73,14 +73,14 @@ conflicting.each do |x, y, z|
|
|
73
73
|
rev = ARGV.reverse
|
74
74
|
|
75
75
|
if rev.index { |_x| _x[y] } < rev.index { |_x| _x[z] }
|
76
|
-
hash.
|
76
|
+
hash.store(o1, true)
|
77
77
|
else
|
78
|
-
hash.
|
78
|
+
hash.store(o2, true)
|
79
79
|
end
|
80
80
|
elsif m1
|
81
|
-
hash.
|
81
|
+
hash.store(o1, true)
|
82
82
|
elsif m2
|
83
|
-
hash.
|
83
|
+
hash.store(o2, true)
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
@@ -266,6 +266,6 @@ if PRINT_TIME
|
|
266
266
|
).*(1_000_000)
|
267
267
|
|
268
268
|
puts "\e[38;2;255;255;0m:: Warning total time also depends on your terminal speed!\e[0m"
|
269
|
-
puts "Total Real Time: #{T_FMT % total_real_t}
|
270
|
-
puts "Total CPU Time: #{T_FMT % total_cpu_t}
|
269
|
+
puts "Total Real Time: #{T_FMT % total_real_t}\u03BCs"
|
270
|
+
puts "Total CPU Time: #{T_FMT % total_cpu_t}\u03BCs"
|
271
271
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
/*
|
2
|
+
Validates if a String is integer or not.
|
3
|
+
|
4
|
+
Conditions:
|
5
|
+
- The String can start with - (negative)
|
6
|
+
- If the Argument is a BigInt or Integer, or anything else, return false
|
7
|
+
- The String cannot have anything other than 0 to 9
|
8
|
+
- The String can have leading zeroes and negative sign:
|
9
|
+
Example 1: "-00999" which translates to Ruby's -999 (decimal)
|
10
|
+
Example 2: "000999" translates to 999
|
11
|
+
- If it fails to determine, it returns nil instead of false
|
12
|
+
- It doesn't raise any error. Handing nil is enough to indicate that it failed.
|
13
|
+
*/
|
14
|
+
|
15
|
+
#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER)
|
16
|
+
#pragma GCC optimize ("O3")
|
17
|
+
#pragma GCC diagnostic warning "-Wall"
|
18
|
+
#elif defined(__clang__)
|
19
|
+
#pragma clang optimize on
|
20
|
+
#pragma clang diagnostic warning "-Wall"
|
21
|
+
#elif defined(__INTEL_COMPILER)
|
22
|
+
#pragma intel optimization_level 3
|
23
|
+
#endif
|
24
|
+
|
25
|
+
#include <limits.h>
|
26
|
+
#include "ruby.h"
|
27
|
+
|
28
|
+
VALUE isNumber(volatile VALUE obj, volatile VALUE val) {
|
29
|
+
// But we don't expect anything other than String though as Argument.
|
30
|
+
// Note that raising ArgumentError or any kind of Error shouldn't be done here
|
31
|
+
// Otherwise Integer(n) is the best method in Ruby.
|
32
|
+
if (!RB_TYPE_P(val, T_STRING))
|
33
|
+
return Qnil ;
|
34
|
+
|
35
|
+
char *str = StringValuePtr(val) ;
|
36
|
+
char ch = str[0] ;
|
37
|
+
|
38
|
+
// If the string is empty, return false
|
39
|
+
if (!ch) return Qfalse ;
|
40
|
+
|
41
|
+
unsigned char i = ch == '-' ? 1 : 0 ;
|
42
|
+
if (!str[i]) return Qfalse ;
|
43
|
+
|
44
|
+
unsigned char max = UCHAR_MAX ;
|
45
|
+
|
46
|
+
# pragma GCC unroll 4
|
47
|
+
while((ch = str[i++])) {
|
48
|
+
if (ch < 48 || ch > 57)
|
49
|
+
return Qfalse ;
|
50
|
+
|
51
|
+
if (i == max)
|
52
|
+
return Qnil ;
|
53
|
+
}
|
54
|
+
|
55
|
+
return Qtrue ;
|
56
|
+
}
|
57
|
+
|
58
|
+
void Init_integer() {
|
59
|
+
VALUE linuxStat = rb_define_module("LinuxStat") ;
|
60
|
+
VALUE misc = rb_define_module_under(linuxStat, "Misc") ;
|
61
|
+
|
62
|
+
rb_define_module_function(misc, "integer?", isNumber, 1) ;
|
63
|
+
}
|
data/ext/procfs/procfs.c
CHANGED
@@ -13,6 +13,7 @@
|
|
13
13
|
#include <stdio.h>
|
14
14
|
#include <unistd.h>
|
15
15
|
#include <string.h>
|
16
|
+
#include <glob.h>
|
16
17
|
#include "ruby.h"
|
17
18
|
#include "uptime.h"
|
18
19
|
#include "statm.h"
|
@@ -22,6 +23,8 @@
|
|
22
23
|
int Init_procfs() {
|
23
24
|
VALUE _linux_stat = rb_define_module("LinuxStat") ;
|
24
25
|
VALUE _procfs = rb_define_module_under(_linux_stat, "ProcFS") ;
|
26
|
+
VALUE _cpu = rb_define_module_under(_linux_stat, "CPU") ;
|
27
|
+
VALUE _process = rb_define_module_under(_linux_stat, "Process") ;
|
25
28
|
|
26
29
|
// uptime
|
27
30
|
rb_define_module_function(_procfs, "uptime_f", uptime_f, 0) ;
|
@@ -40,4 +43,7 @@ int Init_procfs() {
|
|
40
43
|
rb_define_module_function(_procfs, "ps_state", ps_state, 1) ;
|
41
44
|
rb_define_module_function(_procfs, "ps_times", ps_times, 1) ;
|
42
45
|
rb_define_module_function(_procfs, "ps_stat", ps_stat, 1) ;
|
46
|
+
rb_define_module_function(_procfs, "cpu_times", cpuTimes, 0) ;
|
47
|
+
rb_define_module_function(_procfs, "list_process", listProcess, 0) ;
|
48
|
+
|
43
49
|
}
|
data/ext/procfs/stat.h
CHANGED
@@ -17,6 +17,29 @@ static VALUE ps_state(volatile VALUE obj, volatile VALUE pid) {
|
|
17
17
|
return rb_str_new_cstr(_s) ;
|
18
18
|
}
|
19
19
|
|
20
|
+
static VALUE listProcess(volatile VALUE obj) {
|
21
|
+
VALUE ary = rb_ary_new() ;
|
22
|
+
|
23
|
+
glob_t globlist ;
|
24
|
+
int status = glob("/proc/[0-9]*/", GLOB_NOSORT, NULL, &globlist) ;
|
25
|
+
|
26
|
+
if (status == GLOB_NOSPACE || status == GLOB_ABORTED || status == GLOB_NOMATCH) {
|
27
|
+
globfree(&globlist) ;
|
28
|
+
return ary ;
|
29
|
+
}
|
30
|
+
|
31
|
+
char *v, *token ;
|
32
|
+
unsigned int i = 0 ;
|
33
|
+
unsigned int num ;
|
34
|
+
|
35
|
+
while(v = globlist.gl_pathv[i++]) {
|
36
|
+
if (sscanf(v, "/proc/%u", &num) == 1) rb_ary_push(ary, UINT2NUM(num)) ;
|
37
|
+
}
|
38
|
+
|
39
|
+
globfree(&globlist) ;
|
40
|
+
return ary ;
|
41
|
+
}
|
42
|
+
|
20
43
|
static VALUE ps_times(volatile VALUE obj, volatile VALUE pid) {
|
21
44
|
int _pid = FIX2INT(pid) ;
|
22
45
|
if (_pid < 0) return Qnil ;
|
@@ -117,3 +140,46 @@ static VALUE ps_stat(volatile VALUE obj, volatile VALUE pid) {
|
|
117
140
|
INT2NUM(exit_code)
|
118
141
|
) ;
|
119
142
|
}
|
143
|
+
|
144
|
+
static VALUE cpuTimes(volatile VALUE obj) {
|
145
|
+
VALUE ary = rb_ary_new() ;
|
146
|
+
FILE *f = fopen("/proc/stat", "r") ;
|
147
|
+
|
148
|
+
if (!f) return ary ;
|
149
|
+
|
150
|
+
unsigned long user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice ;
|
151
|
+
char line[1024] ;
|
152
|
+
char cpuCode[7] ;
|
153
|
+
float ticks = sysconf(_SC_CLK_TCK) ;
|
154
|
+
char scanStatus ;
|
155
|
+
|
156
|
+
while(fgets(line, 1023, f)) {
|
157
|
+
if (!(line[0] == 'c' && line[1] == 'p' && line[2] == 'u')) break ;
|
158
|
+
|
159
|
+
scanStatus = sscanf(line,
|
160
|
+
"%7[cpu0-9] %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
|
161
|
+
cpuCode, &user, &nice, &system, &idle, &iowait, &irq, &softirq, &steal, &guest, &guest_nice
|
162
|
+
) ;
|
163
|
+
|
164
|
+
if (scanStatus != 11) break ;
|
165
|
+
|
166
|
+
VALUE innerHash = rb_hash_new() ;
|
167
|
+
rb_hash_aset(innerHash, ID2SYM(rb_intern("cpu")), rb_str_new_cstr(cpuCode)) ;
|
168
|
+
rb_hash_aset(innerHash, ID2SYM(rb_intern("user")), rb_float_new(user / ticks)) ;
|
169
|
+
rb_hash_aset(innerHash, ID2SYM(rb_intern("nice")), rb_float_new(nice / ticks)) ;
|
170
|
+
rb_hash_aset(innerHash, ID2SYM(rb_intern("system")), rb_float_new(system / ticks)) ;
|
171
|
+
rb_hash_aset(innerHash, ID2SYM(rb_intern("idle")), rb_float_new(idle / ticks)) ;
|
172
|
+
rb_hash_aset(innerHash, ID2SYM(rb_intern("iowait")), rb_float_new(iowait / ticks)) ;
|
173
|
+
rb_hash_aset(innerHash, ID2SYM(rb_intern("irq")), rb_float_new(irq / ticks)) ;
|
174
|
+
rb_hash_aset(innerHash, ID2SYM(rb_intern("softirq")), rb_float_new(softirq / ticks)) ;
|
175
|
+
rb_hash_aset(innerHash, ID2SYM(rb_intern("steal")), rb_float_new(steal / ticks)) ;
|
176
|
+
rb_hash_aset(innerHash, ID2SYM(rb_intern("guest")), rb_float_new(guest / ticks)) ;
|
177
|
+
rb_hash_aset(innerHash, ID2SYM(rb_intern("guest_nice")), rb_float_new(guest_nice / ticks)) ;
|
178
|
+
|
179
|
+
rb_ary_push(ary, innerHash) ;
|
180
|
+
}
|
181
|
+
|
182
|
+
fclose(f) ;
|
183
|
+
|
184
|
+
return ary ;
|
185
|
+
}
|
data/lib/linux_stat/battery.rb
CHANGED
data/lib/linux_stat/cpu.rb
CHANGED
@@ -21,24 +21,53 @@ module LinuxStat
|
|
21
21
|
#
|
22
22
|
# => {0=>84.38, 1=>100.0, 2=>50.0, 3=>87.5, 4=>87.5}
|
23
23
|
#
|
24
|
+
# It discards any offline CPU or disabled CPU.
|
25
|
+
# For example, if your system CPU has 4 cores, and you disabled core 3, the output will be:
|
26
|
+
# LinuxStat::CPU.stat
|
27
|
+
#
|
28
|
+
# => {0=>26.67, 1=>0.0, 2=>20.0, 4=>20.0}
|
29
|
+
#
|
24
30
|
# If the information is not available, it will return an empty Hash
|
25
31
|
def stat(sleep = ticks_to_ms_t5)
|
26
32
|
return {} unless stat?
|
27
33
|
|
28
|
-
data = IO.readlines('/proc/stat'.freeze).select { |x| x[/^cpu\d*/] }
|
34
|
+
data = IO.readlines('/proc/stat'.freeze).select { |x| x[/^cpu\d*/] }
|
35
|
+
cpu_names1 = []
|
36
|
+
data.map! { |x|
|
37
|
+
splitted = x.split
|
38
|
+
name = splitted.shift[/\d*$/]
|
39
|
+
cpu_names1.push(name.empty? ? 0 : name.to_i + 1)
|
40
|
+
splitted.map!(&:to_f)
|
41
|
+
}
|
42
|
+
|
29
43
|
sleep(sleep)
|
30
|
-
data2 = IO.readlines('/proc/stat'.freeze).select { |x| x[/^cpu\d*/] }
|
44
|
+
data2 = IO.readlines('/proc/stat'.freeze).select { |x| x[/^cpu\d*/] }
|
45
|
+
|
46
|
+
cpu_names2 = []
|
47
|
+
data2.map! { |x|
|
48
|
+
splitted = x.split
|
49
|
+
name = splitted.shift[/\d*$/]
|
50
|
+
cpu_names2.push(name.empty? ? 0 : name.to_i + 1)
|
51
|
+
splitted.map!(&:to_f)
|
52
|
+
}
|
31
53
|
|
32
54
|
# On devices like android, the core count can change anytime (hotplugging).
|
33
55
|
# I had crashes on Termux.
|
34
56
|
# So better just count the min number of CPU and iterate over that
|
35
57
|
# If data.length is smaller than data2.length, we don't have enough data to compare.
|
36
|
-
dl, d2l =
|
37
|
-
|
58
|
+
dl, d2l = cpu_names1.length, cpu_names2.length
|
59
|
+
if dl > d2l
|
60
|
+
min = d2l
|
61
|
+
cpu_cores = cpu_names2
|
62
|
+
else
|
63
|
+
min = dl
|
64
|
+
cpu_cores = cpu_names1
|
65
|
+
end
|
38
66
|
|
39
67
|
min.times.reduce({}) do |h, x|
|
40
|
-
|
41
|
-
|
68
|
+
cpu_core = cpu_cores[x]
|
69
|
+
user, nice, sys, idle, iowait, irq, softirq, steal = *data[x]
|
70
|
+
user2, nice2, sys2, idle2, iowait2, irq2, softirq2, steal2 = *data2[x]
|
42
71
|
|
43
72
|
idle_then, idle_now = idle + iowait, idle2 + iowait2
|
44
73
|
totald = idle_now.+(user2 + nice2 + sys2 + irq2 + softirq2 + steal2) - idle_then.+(user + nice + sys + irq + softirq + steal)
|
@@ -46,7 +75,8 @@ module LinuxStat
|
|
46
75
|
res = totald.-(idle_now - idle_then).fdiv(totald).abs.*(100)
|
47
76
|
res = res.nan? ? 0.0 : res > 100 ? 100.0 : res.round(2)
|
48
77
|
|
49
|
-
h.
|
78
|
+
h.store(cpu_core, res)
|
79
|
+
h
|
50
80
|
end
|
51
81
|
end
|
52
82
|
|
@@ -203,12 +233,16 @@ module LinuxStat
|
|
203
233
|
|
204
234
|
h = {}
|
205
235
|
@@cur_f.each { |id, file|
|
206
|
-
h.
|
236
|
+
h.store(id, IO.read(file).to_i) if File.readable?(file)
|
207
237
|
}
|
208
238
|
|
209
239
|
h
|
210
240
|
end
|
211
241
|
|
242
|
+
def times
|
243
|
+
LinuxStat::ProcFS.cpu_times
|
244
|
+
end
|
245
|
+
|
212
246
|
##
|
213
247
|
# Returns a Hash with max core frequencies corresponding to the CPUs.
|
214
248
|
#
|
@@ -225,7 +259,7 @@ module LinuxStat
|
|
225
259
|
|
226
260
|
h = {}
|
227
261
|
@@min_f.each { |id, file|
|
228
|
-
h.
|
262
|
+
h.store(id, IO.read(file).to_i) if File.readable?(file)
|
229
263
|
}
|
230
264
|
|
231
265
|
h
|
@@ -247,7 +281,7 @@ module LinuxStat
|
|
247
281
|
|
248
282
|
h = {}
|
249
283
|
@@min_f.each { |id, file|
|
250
|
-
h.
|
284
|
+
h.store(id, IO.read(file).to_i) if File.readable?(file)
|
251
285
|
}
|
252
286
|
|
253
287
|
h
|
@@ -271,7 +305,7 @@ module LinuxStat
|
|
271
305
|
|
272
306
|
h = {}
|
273
307
|
@@scaling_g.each { |id, file|
|
274
|
-
h.
|
308
|
+
h.store(id, IO.read(file).tap(&:strip!)) if File.readable?(file)
|
275
309
|
}
|
276
310
|
|
277
311
|
h
|
@@ -293,14 +327,91 @@ module LinuxStat
|
|
293
327
|
|
294
328
|
h = {}
|
295
329
|
@@scaling_av_g.each { |id, file|
|
296
|
-
h.
|
330
|
+
h.store(id, IO.read(file).split.each(&:strip!)) if File.readable?(file)
|
297
331
|
}
|
298
332
|
|
299
333
|
h
|
300
334
|
end
|
301
335
|
|
336
|
+
##
|
337
|
+
# Returns the number of physical cores on the system.
|
338
|
+
#
|
339
|
+
# The return value is an Array of Integers. Each number denoting the physical processor number.
|
340
|
+
# You can later use this to schedule tasks or something else (not provided by LinuxStat).
|
341
|
+
#
|
342
|
+
# However, if the information isn't available on /sys/devices/system/cpu[0-9]*/topology/thread_siblings_list, it will return an empty Array.
|
343
|
+
def physical_core_list
|
344
|
+
physical_cores = []
|
345
|
+
hyperthreaded = {}
|
346
|
+
|
347
|
+
return [] unless File.readable?('/sys/devices/system/cpu/'.freeze)
|
348
|
+
entries = Dir.entries('/sys/devices/system/cpu/'.freeze)
|
349
|
+
entries.delete(?..freeze)
|
350
|
+
entries.delete('..'.freeze)
|
351
|
+
|
352
|
+
entries.each do |x|
|
353
|
+
if x[0..2] == 'cpu'.freeze && LinuxStat::Misc.integer?(x[3..-1])
|
354
|
+
file = "/sys/devices/system/cpu/#{x}/topology/thread_siblings_list"
|
355
|
+
next unless File.readable?(file)
|
356
|
+
|
357
|
+
data = IO.read(file)
|
358
|
+
data.strip!
|
359
|
+
|
360
|
+
val = data.split(?,.freeze).map(&:to_i)
|
361
|
+
val.shift
|
362
|
+
|
363
|
+
# Add items has for fast lookup.
|
364
|
+
# This hash includes all hyper threaded cores that doesn't map to anything.
|
365
|
+
# But this hash has the purpose to look up for items and not include in the list of physical_cores
|
366
|
+
# This is just an array, but can look for keys in O(1), so it's faster than ary.find() { ... }.
|
367
|
+
val.each { |x| hyperthreaded.store(x, nil) }
|
368
|
+
|
369
|
+
key = x[3..-1].to_i
|
370
|
+
physical_cores << key unless hyperthreaded.key?(key)
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
physical_cores
|
375
|
+
end
|
376
|
+
|
377
|
+
##
|
378
|
+
# Returns the number of physical cores on the system.
|
379
|
+
#
|
380
|
+
# The return value is an Array of Integers. Each number denoting the hyperthreaded processor number.
|
381
|
+
# You can later use this to schedule tasks or something else (not provided by LinuxStat).
|
382
|
+
#
|
383
|
+
# However, if the information isn't available on /sys/devices/system/cpu[0-9]*/topology/thread_siblings_list, it will return an empty Array.
|
384
|
+
def hyperthreaded_core_list
|
385
|
+
hyperthreaded = {}
|
386
|
+
|
387
|
+
return [] unless File.readable?('/sys/devices/system/cpu/'.freeze)
|
388
|
+
entries = Dir.entries('/sys/devices/system/cpu/'.freeze)
|
389
|
+
entries.delete(?..freeze)
|
390
|
+
entries.delete('..'.freeze)
|
391
|
+
|
392
|
+
entries.each do |x|
|
393
|
+
if x[0..2] == 'cpu'.freeze && LinuxStat::Misc.integer?(x[3..-1])
|
394
|
+
file = "/sys/devices/system/cpu/#{x}/topology/thread_siblings_list"
|
395
|
+
next unless File.readable?(file)
|
396
|
+
|
397
|
+
data = IO.read(file)
|
398
|
+
data.strip!
|
399
|
+
|
400
|
+
val = data.split(?,.freeze).map(&:to_i)
|
401
|
+
val.shift
|
402
|
+
|
403
|
+
# Add items has for fast lookup to get rid of duplicate items.
|
404
|
+
val.each { |x| hyperthreaded.store(x, nil) unless hyperthreaded.key?(x) }
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
408
|
+
hyperthreaded.keys
|
409
|
+
end
|
410
|
+
|
302
411
|
alias usages stat
|
303
412
|
alias usage total_usage
|
413
|
+
alias physical_cores physical_core_list
|
414
|
+
alias hyperthreaded_cores hyperthreaded_core_list
|
304
415
|
|
305
416
|
private
|
306
417
|
def cpuinfo
|
data/lib/linux_stat/mounts.rb
CHANGED
@@ -58,7 +58,7 @@ module LinuxStat
|
|
58
58
|
def tmpfs
|
59
59
|
ret = {}
|
60
60
|
mounts.each { |x|
|
61
|
-
ret.
|
61
|
+
ret.store(x.split[1], x) if x.start_with?('tmpfs '.freeze)
|
62
62
|
}
|
63
63
|
ret
|
64
64
|
end
|
@@ -115,7 +115,7 @@ module LinuxStat
|
|
115
115
|
|
116
116
|
unless x.empty?
|
117
117
|
_x = x.split
|
118
|
-
m.
|
118
|
+
m.store(_x[0], _x[1])
|
119
119
|
end
|
120
120
|
end
|
121
121
|
m
|
@@ -146,7 +146,7 @@ module LinuxStat
|
|
146
146
|
_x = x.split
|
147
147
|
total, free, available, used = fs_info(_x[1])
|
148
148
|
|
149
|
-
m.
|
149
|
+
m.store(_x[0], {
|
150
150
|
mountpoint: _x[1],
|
151
151
|
|
152
152
|
total: total,
|
data/lib/linux_stat/net.rb
CHANGED
@@ -120,8 +120,8 @@ module LinuxStat
|
|
120
120
|
|
121
121
|
r.each_with_index { |x, i|
|
122
122
|
downcased = x.downcase
|
123
|
-
h.
|
124
|
-
h.
|
123
|
+
h.store(:r, i) if downcased.start_with?('receive'.freeze)
|
124
|
+
h.store(:t, i) if downcased.start_with?('transmit'.freeze)
|
125
125
|
}
|
126
126
|
|
127
127
|
data_0 = data.next.gsub(?|.freeze, ' %'.freeze)
|
data/lib/linux_stat/os.rb
CHANGED
data/lib/linux_stat/pci.rb
CHANGED
@@ -76,7 +76,7 @@ module LinuxStat
|
|
76
76
|
kernel_driver: kernel_driver
|
77
77
|
}
|
78
78
|
|
79
|
-
ret.
|
79
|
+
ret.store(:hwdata, query) unless query.empty?
|
80
80
|
|
81
81
|
ret
|
82
82
|
}
|
@@ -186,14 +186,14 @@ module LinuxStat
|
|
186
186
|
vendor: vendor, device: device
|
187
187
|
}
|
188
188
|
|
189
|
-
ret.
|
190
|
-
ret.
|
189
|
+
ret.store(:sub_vendor, sub_vendor) if sub_vendor
|
190
|
+
ret.store(:sub_device, sub_device) if sub_device
|
191
191
|
|
192
|
-
ret.
|
193
|
-
ret.
|
194
|
-
ret.
|
195
|
-
ret.
|
196
|
-
ret.
|
192
|
+
ret.store(:kernel_driver, kernel_driver) if kernel_driver
|
193
|
+
ret.store(:revision, revision) unless revision.empty?
|
194
|
+
ret.store(:irq, irq) if irq
|
195
|
+
ret.store(:enable, enable) unless enable.nil?
|
196
|
+
ret.store(:hwdata, query) unless query.empty?
|
197
197
|
|
198
198
|
ret
|
199
199
|
rescue StandardError
|
@@ -355,7 +355,7 @@ module LinuxStat
|
|
355
355
|
|
356
356
|
if sub_vendor_id && sub_device_id
|
357
357
|
sub_product = vendor.dig(1, product_id, 1, sub_vendor_id, sub_device_id)
|
358
|
-
ret.
|
358
|
+
ret.store(:sub_system, sub_product) if sub_product
|
359
359
|
end
|
360
360
|
|
361
361
|
ret
|
data/lib/linux_stat/process.rb
CHANGED
@@ -1,25 +1,15 @@
|
|
1
1
|
module LinuxStat
|
2
2
|
# Shows various information about a process that is either
|
3
3
|
# running, sleeping, idle or a zombie.
|
4
|
-
|
5
4
|
module Process
|
6
5
|
class << self
|
7
6
|
##
|
8
7
|
# Returns the list of processes from /proc/.
|
8
|
+
# The output doesn't guarantee a sorted list, in fact it's shuffled most of the time.
|
9
9
|
#
|
10
10
|
# The return type is an Array of Integers.
|
11
11
|
def list
|
12
|
-
|
13
|
-
ret, i = [], -1
|
14
|
-
count = d.length
|
15
|
-
|
16
|
-
while(i += 1) < count
|
17
|
-
pid = File.split(d[i])[1]
|
18
|
-
pid_i = pid.to_i
|
19
|
-
ret << pid_i if pid_i.to_s == pid
|
20
|
-
end
|
21
|
-
|
22
|
-
ret
|
12
|
+
LinuxStat::ProcFS.list_process
|
23
13
|
end
|
24
14
|
|
25
15
|
##
|
@@ -27,7 +17,7 @@ module LinuxStat
|
|
27
17
|
#
|
28
18
|
# The return type is Integer.
|
29
19
|
def count
|
30
|
-
|
20
|
+
LinuxStat::ProcFS.list_process.length
|
31
21
|
end
|
32
22
|
|
33
23
|
##
|
@@ -36,14 +26,14 @@ module LinuxStat
|
|
36
26
|
def names
|
37
27
|
h, i = {}, -1
|
38
28
|
|
39
|
-
l =
|
29
|
+
l = LinuxStat::ProcFS.list_process
|
40
30
|
count = l.length
|
41
31
|
|
42
32
|
while(i += 1) < count
|
43
33
|
x = l[i]
|
44
34
|
|
45
35
|
begin
|
46
|
-
h.
|
36
|
+
h.store(x, IO.read("/proc/#{x}/comm").strip)
|
47
37
|
rescue StandardError
|
48
38
|
end
|
49
39
|
end
|
@@ -57,7 +47,7 @@ module LinuxStat
|
|
57
47
|
def cmdlines
|
58
48
|
h, i = {}, -1
|
59
49
|
|
60
|
-
l =
|
50
|
+
l = LinuxStat::ProcFS.list_process
|
61
51
|
count = l.length
|
62
52
|
|
63
53
|
while(i += 1) < count
|
@@ -66,7 +56,7 @@ module LinuxStat
|
|
66
56
|
begin
|
67
57
|
cmdlines = IO.read("/proc/#{x}/cmdline").strip
|
68
58
|
cmdlines.gsub!(?\u0000.freeze, ?\s.freeze)
|
69
|
-
h.
|
59
|
+
h.store(x, cmdlines)
|
70
60
|
rescue StandardError
|
71
61
|
end
|
72
62
|
end
|
@@ -78,14 +68,14 @@ module LinuxStat
|
|
78
68
|
def types
|
79
69
|
h, i = {}, -1
|
80
70
|
|
81
|
-
l =
|
71
|
+
l = LinuxStat::ProcFS.list_process
|
82
72
|
count = l.length
|
83
73
|
|
84
74
|
while(i += 1) < count
|
85
75
|
x = l[i]
|
86
76
|
|
87
77
|
begin
|
88
|
-
h.
|
78
|
+
h.store(x,
|
89
79
|
case LinuxStat::ProcFS.ps_state(x)
|
90
80
|
when ?S.freeze then :sleeping
|
91
81
|
when ?I.freeze then :idle
|
@@ -109,7 +99,7 @@ module LinuxStat
|
|
109
99
|
# Returns all the id of processes that are sleeping.
|
110
100
|
# The return type is an Array of Integers.
|
111
101
|
def sleeping
|
112
|
-
|
102
|
+
LinuxStat::ProcFS.list_process.select { |x|
|
113
103
|
LinuxStat::ProcFS.ps_state(x) == ?S.freeze
|
114
104
|
}
|
115
105
|
end
|
@@ -118,7 +108,7 @@ module LinuxStat
|
|
118
108
|
# Returns all the id of processes that are idle.
|
119
109
|
# The return type is an Array of Integers.
|
120
110
|
def idle
|
121
|
-
|
111
|
+
LinuxStat::ProcFS.list_process.select { |x|
|
122
112
|
LinuxStat::ProcFS.ps_state(x) == ?I.freeze
|
123
113
|
}
|
124
114
|
end
|
@@ -127,7 +117,7 @@ module LinuxStat
|
|
127
117
|
# Returns all the id of processes that are zombies.
|
128
118
|
# The return type is an Array of Integers.
|
129
119
|
def zombie
|
130
|
-
|
120
|
+
LinuxStat::ProcFS.list_process.select { |x|
|
131
121
|
LinuxStat::ProcFS.ps_state(x) == ?Z.freeze
|
132
122
|
}
|
133
123
|
end
|
@@ -136,7 +126,7 @@ module LinuxStat
|
|
136
126
|
# Returns all the id of processes that are running.
|
137
127
|
# The return type is an Array of Integers.
|
138
128
|
def running
|
139
|
-
|
129
|
+
LinuxStat::ProcFS.list_process.select { |x|
|
140
130
|
LinuxStat::ProcFS.ps_state(x) == ?R.freeze
|
141
131
|
}
|
142
132
|
end
|
@@ -145,7 +135,7 @@ module LinuxStat
|
|
145
135
|
# Returns all the id of processes that are stopped.
|
146
136
|
# The return type is an Array of Integers.
|
147
137
|
def stopped
|
148
|
-
|
138
|
+
LinuxStat::ProcFS.list_process.select { |x|
|
149
139
|
v = LinuxStat::ProcFS.ps_state(x)
|
150
140
|
v == ?T.freeze || v == ?t.freeze
|
151
141
|
}
|
data/lib/linux_stat/swap.rb
CHANGED
@@ -13,7 +13,8 @@ module LinuxStat
|
|
13
13
|
file = IO.readlines('/proc/swaps'.freeze).drop(1)
|
14
14
|
file.reduce({}) do |h, x|
|
15
15
|
name, *stats = x.strip.split
|
16
|
-
h.
|
16
|
+
h.store(name, stats.map! { |v| LinuxStat::Misc.integer?(v) ? v.to_i : v.to_sym })
|
17
|
+
h
|
17
18
|
end
|
18
19
|
end
|
19
20
|
|
data/lib/linux_stat/thermal.rb
CHANGED
@@ -107,10 +107,10 @@ module LinuxStat
|
|
107
107
|
|
108
108
|
h = {path: path, name: name}
|
109
109
|
|
110
|
-
h.
|
111
|
-
h.
|
112
|
-
h.
|
113
|
-
h.
|
110
|
+
h.store(:label, label) if label
|
111
|
+
h.store(key, value)
|
112
|
+
h.store(:temp_crit, temp_crit) if temp_crit
|
113
|
+
h.store(:temp_crit, temp_max) if temp_max
|
114
114
|
|
115
115
|
ret.push(h)
|
116
116
|
end
|
data/lib/linux_stat/usb.rb
CHANGED
@@ -102,20 +102,20 @@ module LinuxStat
|
|
102
102
|
vendor_id: id_vendor, product_id: id_product
|
103
103
|
}
|
104
104
|
|
105
|
-
ret.
|
106
|
-
ret.
|
105
|
+
ret.store(:bus_num, bus_num.to_i) unless bus_num.empty?
|
106
|
+
ret.store(:dev_num, dev_num.to_i) unless dev_num.empty?
|
107
107
|
|
108
|
-
ret.
|
108
|
+
ret.store(:serial, serial) unless serial.empty?
|
109
109
|
|
110
|
-
ret.
|
111
|
-
ret.
|
112
|
-
ret.
|
110
|
+
ret.store(:hwdata, query) unless query.empty?
|
111
|
+
ret.store(:product, product) unless product.empty?
|
112
|
+
ret.store(:manufacturer, manufacturer) unless manufacturer.empty?
|
113
113
|
|
114
|
-
ret.
|
115
|
-
ret.
|
114
|
+
ret.store(:removable, is_removable) unless is_removable.nil?
|
115
|
+
ret.store(:authorized, authorized == 1)
|
116
116
|
|
117
|
-
ret.
|
118
|
-
ret.
|
117
|
+
ret.store(:b_max_power, b_max_power) unless b_max_power.empty?
|
118
|
+
ret.store(:b_max_packet_size0, b_max_packet_size0) if b_max_packet_size0
|
119
119
|
|
120
120
|
ret
|
121
121
|
rescue StandardError
|
data/lib/linux_stat/user.rb
CHANGED
@@ -25,9 +25,11 @@ module LinuxStat
|
|
25
25
|
def ids
|
26
26
|
return {} unless passwd_readable?
|
27
27
|
passwd_splitted.reduce({}) { |h, x|
|
28
|
-
h.
|
28
|
+
h.store(x[0].to_sym, {
|
29
29
|
uid: x[2].to_i, gid: x[3].to_i
|
30
30
|
})
|
31
|
+
|
32
|
+
h
|
31
33
|
}
|
32
34
|
end
|
33
35
|
|
@@ -42,8 +44,10 @@ module LinuxStat
|
|
42
44
|
def uids
|
43
45
|
return {} unless passwd_readable?
|
44
46
|
passwd_splitted.reduce({}) { |h, x|
|
45
|
-
h.
|
47
|
+
h.store(x[0].to_sym, x[2].to_i)
|
48
|
+
h
|
46
49
|
}
|
50
|
+
|
47
51
|
end
|
48
52
|
|
49
53
|
##
|
@@ -59,7 +63,8 @@ module LinuxStat
|
|
59
63
|
return {} unless passwd_readable?
|
60
64
|
|
61
65
|
passwd_splitted.reduce({}) { |h, x|
|
62
|
-
h.
|
66
|
+
h.store(x[0].to_sym, x[3].to_i)
|
67
|
+
h
|
63
68
|
}
|
64
69
|
end
|
65
70
|
|
@@ -76,7 +81,8 @@ module LinuxStat
|
|
76
81
|
return {} unless passwd_readable?
|
77
82
|
passwd.reduce({}) { |h, x|
|
78
83
|
splitted = x.split(?:)
|
79
|
-
h.
|
84
|
+
h.store(splitted[0].to_sym, splitted[5])
|
85
|
+
h
|
80
86
|
}
|
81
87
|
end
|
82
88
|
|
data/lib/linux_stat/version.rb
CHANGED
data/lib/linux_stat.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: linux_stat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.5.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sourav Goswami
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-10-23 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Linux only, efficient linux system utilization reporting and system monitoring
|
14
14
|
gem
|
@@ -18,6 +18,7 @@ executables:
|
|
18
18
|
- linuxstat.rb
|
19
19
|
extensions:
|
20
20
|
- ext/fs_stat/extconf.rb
|
21
|
+
- ext/misc/integer/extconf.rb
|
21
22
|
- ext/nproc/extconf.rb
|
22
23
|
- ext/procfs/extconf.rb
|
23
24
|
- ext/sysconf/extconf.rb
|
@@ -35,6 +36,8 @@ files:
|
|
35
36
|
- ext/fs_stat/extconf.rb
|
36
37
|
- ext/fs_stat/fs_stat.c
|
37
38
|
- ext/fs_stat/sector_size.h
|
39
|
+
- ext/misc/integer/extconf.rb
|
40
|
+
- ext/misc/integer/integer?.c
|
38
41
|
- ext/nproc/extconf.rb
|
39
42
|
- ext/nproc/nproc.c
|
40
43
|
- ext/procfs/extconf.rb
|
@@ -87,7 +90,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
87
90
|
- !ruby/object:Gem::Version
|
88
91
|
version: '0'
|
89
92
|
requirements: []
|
90
|
-
rubygems_version: 3.2.
|
93
|
+
rubygems_version: 3.2.29
|
91
94
|
signing_key:
|
92
95
|
specification_version: 4
|
93
96
|
summary: Efficient linux system reporting gem
|