linux_stat 2.3.0 → 2.5.2
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.
- 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
|