linux_stat 0.7.4 → 0.9.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 +527 -316
- data/exe/linuxstat.rb +34 -13
- data/ext/fs_stat/fs_stat.c +9 -2
- data/ext/nproc/extconf.rb +11 -0
- data/ext/nproc/nproc.c +31 -0
- data/ext/sysconf/sysconf.c +78 -11
- data/ext/utsname/utsname.c +26 -14
- data/lib/linux_stat.rb +7 -1
- data/lib/linux_stat/battery.rb +183 -20
- data/lib/linux_stat/cpu.rb +222 -41
- data/lib/linux_stat/filesystem.rb +12 -12
- data/lib/linux_stat/kernel.rb +1 -1
- data/lib/linux_stat/os.rb +2 -2
- data/lib/linux_stat/prettify_bytes.rb +1 -4
- data/lib/linux_stat/process.rb +1 -1
- data/lib/linux_stat/process_info.rb +124 -18
- data/lib/linux_stat/swap.rb +1 -1
- data/lib/linux_stat/version.rb +1 -1
- metadata +5 -2
data/lib/linux_stat/cpu.rb
CHANGED
@@ -2,7 +2,7 @@ module LinuxStat
|
|
2
2
|
module CPU
|
3
3
|
class << self
|
4
4
|
##
|
5
|
-
# = stat(sleep = 1.0 / LinuxStat::Sysconf.sc_clk_tck)
|
5
|
+
# = stat(sleep = 1.0 / LinuxStat::Sysconf.sc_clk_tck * 5)
|
6
6
|
#
|
7
7
|
# Where sleep is the delay to gather the data.
|
8
8
|
#
|
@@ -14,18 +14,20 @@ module LinuxStat
|
|
14
14
|
#
|
15
15
|
# And the consecutive ones are the real core usages.
|
16
16
|
#
|
17
|
-
#
|
18
|
-
#
|
17
|
+
# For example, on a system with 4 threads:
|
18
|
+
# LinuxStat::CPU.stat
|
19
|
+
#
|
20
|
+
# => {0=>84.38, 1=>100.0, 2=>50.0, 3=>87.5, 4=>87.5}
|
19
21
|
#
|
20
22
|
# If the information is not available, it will return an empty Hash
|
21
|
-
def stat(sleep =
|
23
|
+
def stat(sleep = ticks_to_ms_t5)
|
22
24
|
return {} unless stat?
|
23
25
|
|
24
|
-
data = IO.readlines('/proc/stat').select
|
26
|
+
data = IO.readlines('/proc/stat'.freeze).select { |x| x[/^cpu\d*/] }.map! { |x| x.split.map!(&:to_f) }
|
25
27
|
sleep(sleep)
|
26
|
-
data2 = IO.readlines('/proc/stat').select
|
28
|
+
data2 = IO.readlines('/proc/stat'.freeze).select { |x| x[/^cpu\d*/] }.map! { |x| x.split.map!(&:to_f) }
|
27
29
|
|
28
|
-
# On devices like android, the core count can change anytime.
|
30
|
+
# On devices like android, the core count can change anytime (hotplugging).
|
29
31
|
# I had crashes on Termux.
|
30
32
|
# So better just count the min number of CPU and iterate over that
|
31
33
|
# If data.length is smaller than data2.length, we don't have enough data to compare.
|
@@ -39,12 +41,10 @@ module LinuxStat
|
|
39
41
|
idle_then, idle_now = idle + iowait, idle2 + iowait2
|
40
42
|
totald = idle_now.+(user2 + nice2 + sys2 + irq2 + softirq2 + steal2) - idle_then.+(user + nice + sys + irq + softirq + steal)
|
41
43
|
|
42
|
-
res = totald.-(idle_now - idle_then).fdiv(totald).*(100)
|
43
|
-
res = 0.0
|
44
|
+
res = totald.-(idle_now - idle_then).fdiv(totald).abs.*(100)
|
45
|
+
res = res.nan? ? 0.0 : res > 100 ? 100.0 : res.round(2)
|
44
46
|
|
45
|
-
h.merge!(
|
46
|
-
x => res
|
47
|
-
)
|
47
|
+
h.merge!( x => res )
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
@@ -60,28 +60,119 @@ module LinuxStat
|
|
60
60
|
# It's like running LinuxStat::CPU.stat[0] but it's much more efficient and calculates just the aggregated usage which is available at the top of the /proc/stat file.
|
61
61
|
#
|
62
62
|
# If the information is not available, it will return nil.
|
63
|
-
def total_usage(sleep =
|
63
|
+
def total_usage(sleep = ticks_to_ms_t5)
|
64
64
|
return nil unless stat?
|
65
65
|
|
66
|
-
data = IO.foreach('/proc/stat').first.split.tap(&:shift).map!(&:to_f)
|
66
|
+
data = IO.foreach('/proc/stat'.freeze).first.split.tap(&:shift).map!(&:to_f)
|
67
67
|
sleep(sleep)
|
68
|
-
data2 = IO.foreach('/proc/stat').first.split.tap(&:shift).map!(&:to_f)
|
68
|
+
data2 = IO.foreach('/proc/stat'.freeze).first.split.tap(&:shift).map!(&:to_f)
|
69
69
|
|
70
70
|
user, nice, sys, idle, iowait, irq, softirq, steal = *data
|
71
71
|
user2, nice2, sys2, idle2, iowait2, irq2, softirq2, steal2 = *data2
|
72
72
|
|
73
73
|
idle_then, idle_now = idle + iowait, idle2 + iowait2
|
74
74
|
totald = idle_now.+(user2 + nice2 + sys2 + irq2 + softirq2 + steal2) - idle_then.+(user + nice + sys + irq + softirq + steal)
|
75
|
-
|
75
|
+
|
76
|
+
u = totald.-(idle_now - idle_then).fdiv(totald).abs.*(100)
|
77
|
+
u > 100 ? 100.0 : u.round(2)
|
76
78
|
end
|
77
79
|
|
78
80
|
##
|
79
|
-
# Returns the total number of CPU
|
81
|
+
# Returns the total number of CPU available for the sysetm.
|
82
|
+
#
|
83
|
+
# It returns an Integer.
|
80
84
|
#
|
81
|
-
# If the information isn't available, it will return
|
85
|
+
# If the information isn't available, it will return nil.
|
82
86
|
def count
|
83
|
-
|
84
|
-
|
87
|
+
@@cpu_count ||= LinuxStat::Sysconf.processor_configured
|
88
|
+
end
|
89
|
+
|
90
|
+
##
|
91
|
+
# Returns the total number of CPU online in the sysetm.
|
92
|
+
#
|
93
|
+
# It first reads /proc/stat, if that fails, it will
|
94
|
+
# read /sys/devices/system/cpu/online,
|
95
|
+
# if that fails it will open /proc/cpuinfo.
|
96
|
+
# If neither of the procedures work, it will get the
|
97
|
+
# LinuxStat::Sysconf.processor_online
|
98
|
+
#
|
99
|
+
# It opens /sys/devices/system/cpu/offline and
|
100
|
+
# performs various job to get one Ruby array.
|
101
|
+
#
|
102
|
+
# If the information isn't available, it will return an empty Array.
|
103
|
+
def count_online
|
104
|
+
@@cpuinfo_file ||= '/proc/cpuinfo'.freeze
|
105
|
+
@@cpuinfo_readable ||= File.readable?(@@cpuinfo_file)
|
106
|
+
|
107
|
+
@@stat_file ||= '/proc/stat'.freeze
|
108
|
+
|
109
|
+
# Not much slow, not blazing fast, somewhat reliable
|
110
|
+
get_online = online
|
111
|
+
|
112
|
+
if !get_online.empty?
|
113
|
+
get_online.length
|
114
|
+
elsif @@cpuinfo_readable
|
115
|
+
# Way slower but reliable!
|
116
|
+
IO.readlines(@@cpuinfo_file).count { |x| x.strip[/\Aprocessor.*\d*\z/] }
|
117
|
+
else
|
118
|
+
# Way faster but absolutely unrealiable!
|
119
|
+
LinuxStat::Sysconf.processor_online
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
##
|
124
|
+
# Returns the total number of CPU online in the sysetm.
|
125
|
+
#
|
126
|
+
# It will read /proc/stat to get the info.
|
127
|
+
#
|
128
|
+
# If the info isn't available, it reads /sys/devices/system/cpu/onfline and
|
129
|
+
# performs various job to get one Ruby array.
|
130
|
+
#
|
131
|
+
# If the information isn't available, it will return an empty Array.
|
132
|
+
def online
|
133
|
+
@@online_file ||= '/sys/devices/system/cpu/online'.freeze
|
134
|
+
@@online_readable ||= File.readable?(@@online_file)
|
135
|
+
|
136
|
+
@@stat_file ||= '/proc/stat'.freeze
|
137
|
+
|
138
|
+
ret = []
|
139
|
+
|
140
|
+
if stat?
|
141
|
+
IO.readlines(@@stat_file).map { |x|
|
142
|
+
v = x.strip[/\Acpu\d*/] &.[](/\d/)
|
143
|
+
ret << v.to_i if v
|
144
|
+
}
|
145
|
+
elsif @@online_readable
|
146
|
+
IO.read(@@online_file).split(?,.freeze).each { |x|
|
147
|
+
x.strip!
|
148
|
+
c = x.split(?-.freeze).map(&:to_i)
|
149
|
+
ret.concat(c.length == 2 ? Range.new(*c).to_a : c)
|
150
|
+
}
|
151
|
+
end
|
152
|
+
|
153
|
+
ret
|
154
|
+
end
|
155
|
+
|
156
|
+
##
|
157
|
+
# Returns the total number of CPU offline in the sysetm.
|
158
|
+
#
|
159
|
+
# It opens /sys/devices/system/cpu/offline and
|
160
|
+
# performs various job to get one Ruby array.
|
161
|
+
#
|
162
|
+
# If the information isn't available, it will return an empty Array.
|
163
|
+
def offline
|
164
|
+
@@offline_file ||= '/sys/devices/system/cpu/offline'.freeze
|
165
|
+
@@offline_readable ||= File.readable?(@@offline_file)
|
166
|
+
return [] unless @@offline_readable
|
167
|
+
|
168
|
+
ret = []
|
169
|
+
IO.read(@@offline_file).split(?,.freeze).each { |x|
|
170
|
+
x.strip!
|
171
|
+
c = x.split(?-.freeze).map(&:to_i)
|
172
|
+
ret.concat(c.length == 2 ? Range.new(*c).to_a : c)
|
173
|
+
}
|
174
|
+
|
175
|
+
ret
|
85
176
|
end
|
86
177
|
|
87
178
|
##
|
@@ -95,33 +186,115 @@ module LinuxStat
|
|
95
186
|
end
|
96
187
|
|
97
188
|
##
|
98
|
-
# Returns
|
189
|
+
# Returns a Hash with current core frequencies corresponding to the CPUs.
|
190
|
+
#
|
191
|
+
# For example:
|
192
|
+
# LinuxStat::CPU.cur_freq
|
99
193
|
#
|
100
|
-
#
|
194
|
+
# => {"cpu0"=>1999990, "cpu1"=>2000042, "cpu2"=>2000016, "cpu3"=>2000088}
|
195
|
+
#
|
196
|
+
# If the information isn't available, it will return an empty Hash.
|
101
197
|
def cur_freq
|
102
|
-
@@
|
103
|
-
|
198
|
+
@@cur_f ||= cpus.map { |x|
|
199
|
+
[File.split(x)[-1], File.join(x, 'cpufreq/scaling_cur_freq'.freeze)]
|
200
|
+
}
|
104
201
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
202
|
+
h = {}
|
203
|
+
@@cur_f.each { |id, file|
|
204
|
+
h.merge!(id => IO.read(file).to_i) if File.readable?(file)
|
205
|
+
}
|
206
|
+
|
207
|
+
h
|
110
208
|
end
|
111
209
|
|
112
210
|
##
|
113
|
-
# Returns
|
211
|
+
# Returns a Hash with max core frequencies corresponding to the CPUs.
|
212
|
+
#
|
213
|
+
# For example:
|
214
|
+
# LinuxStat::CPU.min_freq
|
114
215
|
#
|
115
|
-
#
|
216
|
+
# => {"cpu0"=>2000000, "cpu1"=>2000000, "cpu2"=>2000000, "cpu3"=>2000000}
|
217
|
+
#
|
218
|
+
# If the information isn't available, it will return an empty Hash.
|
219
|
+
def min_freq
|
220
|
+
@@min_f ||= cpus.map { |x|
|
221
|
+
[File.split(x)[-1], File.join(x, 'cpufreq/scaling_min_freq'.freeze)]
|
222
|
+
}
|
223
|
+
|
224
|
+
h = {}
|
225
|
+
@@min_f.each { |id, file|
|
226
|
+
h.merge!(id => IO.read(file).to_i) if File.readable?(file)
|
227
|
+
}
|
228
|
+
|
229
|
+
h
|
230
|
+
end
|
231
|
+
|
232
|
+
##
|
233
|
+
# Returns a Hash with max core frequencies corresponding to the CPUs.
|
234
|
+
#
|
235
|
+
# For example:
|
236
|
+
# LinuxStat::CPU.max_freq
|
237
|
+
#
|
238
|
+
# => {"cpu0"=>2000000, "cpu1"=>2000000, "cpu2"=>2000000, "cpu3"=>2000000}
|
239
|
+
#
|
240
|
+
# If the information isn't available, it will return an empty Hash.
|
116
241
|
def max_freq
|
117
|
-
@@
|
118
|
-
|
242
|
+
@@min_f ||= cpus.map { |x|
|
243
|
+
[File.split(x)[-1], File.join(x, 'cpufreq/scaling_max_freq'.freeze)]
|
244
|
+
}
|
119
245
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
246
|
+
h = {}
|
247
|
+
@@min_f.each { |id, file|
|
248
|
+
h.merge!(id => IO.read(file).to_i) if File.readable?(file)
|
249
|
+
}
|
250
|
+
|
251
|
+
h
|
252
|
+
end
|
253
|
+
|
254
|
+
##
|
255
|
+
# Returns the corresponding governor of each CPU.
|
256
|
+
#
|
257
|
+
# The return type is a Hash.
|
258
|
+
#
|
259
|
+
# For example:
|
260
|
+
# LinuxStat::CPU.governor
|
261
|
+
#
|
262
|
+
# => {"cpu0"=>"powersave", "cpu1"=>"powersave", "cpu2"=>"performance", "cpu3"=>"performance"}
|
263
|
+
#
|
264
|
+
# If the information isn't available, it will return an empty Hash.
|
265
|
+
def governor
|
266
|
+
@@scaling_g ||= cpus.map { |x|
|
267
|
+
[File.split(x)[-1], File.join(x, 'cpufreq/scaling_governor'.freeze)]
|
268
|
+
}
|
269
|
+
|
270
|
+
h = {}
|
271
|
+
@@scaling_g.each { |id, file|
|
272
|
+
h.merge!(id => IO.read(file).tap(&:strip!)) if File.readable?(file)
|
273
|
+
}
|
274
|
+
|
275
|
+
h
|
276
|
+
end
|
277
|
+
|
278
|
+
##
|
279
|
+
# Returns an array of governors for each CPU as a Hash.
|
280
|
+
#
|
281
|
+
# For example:
|
282
|
+
# LinuxStat::CPU.available_governors
|
283
|
+
#
|
284
|
+
# => {"cpu0"=>["performance", "powersave"], "cpu1"=>["performance", "powersave"], "cpu2"=>["performance", "powersave"], "cpu3"=>["performance", "powersave"]}
|
285
|
+
#
|
286
|
+
# If the information isn't available, it will return an empty Hash.
|
287
|
+
def available_governors
|
288
|
+
@@scaling_av_g ||= cpus.map { |x|
|
289
|
+
[File.split(x)[-1], File.join(x, 'cpufreq/scaling_available_governors'.freeze)]
|
290
|
+
}
|
291
|
+
|
292
|
+
h = {}
|
293
|
+
@@scaling_av_g.each { |id, file|
|
294
|
+
h.merge!(id => IO.read(file).split.each(&:strip!)) if File.readable?(file)
|
295
|
+
}
|
296
|
+
|
297
|
+
h
|
125
298
|
end
|
126
299
|
|
127
300
|
alias usages stat
|
@@ -129,15 +302,23 @@ module LinuxStat
|
|
129
302
|
|
130
303
|
private
|
131
304
|
def cpuinfo
|
132
|
-
File.readable?('/proc/cpuinfo') ? IO.readlines('/proc/cpuinfo') : []
|
305
|
+
File.readable?('/proc/cpuinfo') ? IO.readlines('/proc/cpuinfo').freeze : [].freeze
|
133
306
|
end
|
134
307
|
|
135
308
|
def stat?
|
136
309
|
@@stat_readable ||= File.readable?('/proc/stat')
|
137
310
|
end
|
138
311
|
|
139
|
-
|
140
|
-
|
312
|
+
# Just to avoid duplicate calculations
|
313
|
+
# ticks to ms times 5
|
314
|
+
# If the ticks is 100, it will return 0.05
|
315
|
+
def ticks_to_ms_t5
|
316
|
+
@@sc_clk_tck ||= LinuxStat::Sysconf.sc_clk_tck.to_i
|
317
|
+
@@ms_t5 ||= 1.0 / (@@sc_clk_tck < 1 ? 100 : @@sc_clk_tck) * 5
|
318
|
+
end
|
319
|
+
|
320
|
+
def cpus
|
321
|
+
@@all_cpu = Dir["/sys/devices/system/cpu/cpu[0-9]*/"].sort!.freeze
|
141
322
|
end
|
142
323
|
end
|
143
324
|
end
|
@@ -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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
108
|
+
def stat_raw(fs = ?..freeze)
|
109
109
|
LinuxStat::FS.stat(fs)
|
110
110
|
end
|
111
111
|
end
|
data/lib/linux_stat/kernel.rb
CHANGED
data/lib/linux_stat/os.rb
CHANGED
@@ -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
|
146
|
+
@@uptime_readable ||= File.readable?('/proc/uptime')
|
147
147
|
end
|
148
148
|
end
|
149
149
|
end
|