linux_stat 0.5.1 → 0.6.4
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 +292 -55
- data/exe/linuxstat.rb +1 -1
- data/ext/fs_stat/extconf.rb +5 -1
- data/ext/fs_stat/fs_stat.c +2 -0
- data/ext/sysconf/extconf.rb +5 -1
- data/ext/sysconf/sysconf.c +6 -2
- data/ext/utsname/extconf.rb +5 -1
- data/ext/utsname/utsname.c +2 -0
- data/lib/linux_stat.rb +32 -5
- data/lib/linux_stat/battery.rb +20 -1
- data/lib/linux_stat/bios.rb +8 -0
- data/lib/linux_stat/cpu.rb +32 -6
- data/lib/linux_stat/filesystem.rb +31 -10
- data/lib/linux_stat/kernel.rb +36 -2
- data/lib/linux_stat/memory.rb +7 -0
- data/lib/linux_stat/mounts.rb +176 -1
- data/lib/linux_stat/net.rb +119 -1
- data/lib/linux_stat/os.rb +15 -3
- data/lib/linux_stat/prettify_bytes.rb +110 -0
- data/lib/linux_stat/process.rb +10 -0
- data/lib/linux_stat/process_info.rb +223 -91
- data/lib/linux_stat/swap.rb +15 -1
- data/lib/linux_stat/user.rb +119 -26
- data/lib/linux_stat/version.rb +1 -1
- metadata +3 -2
data/lib/linux_stat/kernel.rb
CHANGED
@@ -1,16 +1,22 @@
|
|
1
1
|
module LinuxStat
|
2
2
|
module Kernel
|
3
3
|
class << self
|
4
|
+
##
|
4
5
|
# Returns the Linux Kernel version.
|
6
|
+
#
|
5
7
|
# If the information isn't available, it will return a frozen empty string.
|
8
|
+
#
|
6
9
|
# The output is also cached (memoized) ; as changing the value in runtime is unexpected.
|
7
10
|
def version
|
8
11
|
return ''.freeze if string.empty?
|
9
12
|
@@version ||= splitted[2]
|
10
13
|
end
|
11
14
|
|
15
|
+
##
|
12
16
|
# Returns the name of the user who built the kernel using KBUILD_FLAGS.
|
17
|
+
#
|
13
18
|
# If the information isn't available, it will return a frozen empty string.
|
19
|
+
#
|
14
20
|
# The output is also cached (memoized) ; as changing the value in runtime is unexpected.
|
15
21
|
def build_user
|
16
22
|
@@build_user ||= string.split(/(\(.+\))/).each(&:strip!)
|
@@ -18,8 +24,11 @@ module LinuxStat
|
|
18
24
|
.split[0].to_s[1..-2].to_s.freeze
|
19
25
|
end
|
20
26
|
|
27
|
+
##
|
21
28
|
# Returns the compiler used to compile the Linux Kernel.
|
29
|
+
#
|
22
30
|
# If the information isn't available, it will return a frozen empty string.
|
31
|
+
#
|
23
32
|
# The output is also cached (memoized) ; as changing the value in runtime is unexpected.
|
24
33
|
def compiler
|
25
34
|
return ''.freeze if string.empty?
|
@@ -37,8 +46,11 @@ module LinuxStat
|
|
37
46
|
end << compiler_version
|
38
47
|
end
|
39
48
|
|
49
|
+
##
|
40
50
|
# Returns the compiler version used to compile the Linux Kernel.
|
51
|
+
#
|
41
52
|
# If the information isn't available, it will return a frozen empty string.
|
53
|
+
#
|
42
54
|
# The output is also cached (memoized) ; as changing the value in runtime is unexpected.
|
43
55
|
def compiler_version
|
44
56
|
@@compiler_version ||= string.split(/(\(.+?\))/).each(&:strip!)
|
@@ -46,20 +58,28 @@ module LinuxStat
|
|
46
58
|
.find { |x| x[/[\d.]+/] }.to_s[/[\d.]+/].to_s.freeze
|
47
59
|
end
|
48
60
|
|
61
|
+
##
|
49
62
|
# Returns the time when the kernel was compiled.
|
63
|
+
#
|
50
64
|
# The return value is a Time object.
|
65
|
+
#
|
51
66
|
# If the information isn't available, it will return nil
|
52
67
|
#
|
53
68
|
# The time will be searched in specific order.
|
54
|
-
#
|
69
|
+
#
|
70
|
+
# * It will match any date matching any of these formats:
|
55
71
|
# 1. %b %d %H:%M:%S %z %Y
|
56
72
|
# 2. %d %b %Y %H:%M:%S %z
|
57
73
|
# 3. %Y-%m-%d
|
74
|
+
#
|
58
75
|
# Most kernels have date in them in this format.
|
59
76
|
#
|
60
77
|
# Do note that Ruby sometimes fails to work with timezones like BST for example.
|
78
|
+
#
|
61
79
|
# In such case, the timezone is unrealiable and often returns the local timezone.
|
80
|
+
#
|
62
81
|
# You have to use regexp yourself to get the proper zone.
|
82
|
+
#
|
63
83
|
# Use LinuxStat::Kernel.build_date_string to get the original string if you need that.
|
64
84
|
#
|
65
85
|
# The output is also cached (memoized) ; as changing the value in runtime is unexpected.
|
@@ -91,20 +111,29 @@ module LinuxStat
|
|
91
111
|
end
|
92
112
|
end
|
93
113
|
|
114
|
+
##
|
94
115
|
# Returns the time when the kernel was compiled.
|
116
|
+
#
|
95
117
|
# The return value is a String.
|
118
|
+
#
|
96
119
|
# If the information isn't available, it will return nil
|
97
120
|
#
|
98
121
|
# The time will be searched in specific order.
|
99
|
-
#
|
122
|
+
#
|
123
|
+
# * It will match any date matching any of these formats:
|
124
|
+
#
|
100
125
|
# 1. %b %d %H:%M:%S %z %Y
|
101
126
|
# 2. %d %b %Y %H:%M:%S %z
|
102
127
|
# 3. %Y-%m-%d
|
128
|
+
#
|
103
129
|
# Most kernels have date in them in this format.
|
104
130
|
#
|
105
131
|
# Do note that Ruby sometimes fails to work with timezones like BST for example.
|
132
|
+
#
|
106
133
|
# In such case, the timezone is unrealiable and often returns the local timezone.
|
134
|
+
#
|
107
135
|
# You have to use regexp yourself to get the proper zone.
|
136
|
+
#
|
108
137
|
# Use LinuxStat::Kernel.build_date_string to get the original string if you need that.
|
109
138
|
#
|
110
139
|
# The output is also cached (memoized) ; as changing the value in runtime is unexpected.
|
@@ -133,14 +162,19 @@ module LinuxStat
|
|
133
162
|
end
|
134
163
|
end
|
135
164
|
|
165
|
+
##
|
136
166
|
# Reads maximum 1024 bytes from /proc/version and returns the string.
|
167
|
+
#
|
137
168
|
# The output is also cached ; as changing the value in runtime is unexpected.
|
138
169
|
def string
|
139
170
|
@@string ||= File.readable?('/proc/version') ? IO.read('/proc/version', 1024).tap(&:strip!) : ''
|
140
171
|
end
|
141
172
|
|
173
|
+
##
|
142
174
|
# Returns the sc_clk_tck or the same output from command `getconf CLK_TCK`.
|
175
|
+
#
|
143
176
|
# Also, clk_tck is an alias of this method.
|
177
|
+
#
|
144
178
|
# The output is also cached ; as changing the value in runtime is unexpected.
|
145
179
|
def ticks
|
146
180
|
@@tick ||= LinuxStat::Sysconf.sc_clk_tck
|
data/lib/linux_stat/memory.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module LinuxStat
|
2
2
|
module Memory
|
3
3
|
class << self
|
4
|
+
##
|
4
5
|
# Returns the memory details reported by /proc/meminfo. In this format:
|
5
6
|
# {:total=>3836264, :used=>3097952, :available=>738312, :percent_used=>80.75, :percent_available=>19.25}
|
6
7
|
#
|
@@ -20,6 +21,7 @@ module LinuxStat
|
|
20
21
|
percent_available = total == 0 ? 0.0 : available.*(100).fdiv(total).round(2)
|
21
22
|
|
22
23
|
# We have all the methods, but each methods reads the same file
|
24
|
+
#
|
23
25
|
# So better to use the above calculation
|
24
26
|
{
|
25
27
|
total: total,
|
@@ -30,6 +32,7 @@ module LinuxStat
|
|
30
32
|
}
|
31
33
|
end
|
32
34
|
|
35
|
+
##
|
33
36
|
# Returns the total memory details reported by /proc/meminfo.
|
34
37
|
# The value is in Kilobyte.
|
35
38
|
#
|
@@ -39,6 +42,7 @@ module LinuxStat
|
|
39
42
|
IO.foreach('/proc/meminfo').first.split[1].to_i
|
40
43
|
end
|
41
44
|
|
45
|
+
##
|
42
46
|
# Returns the total memory details reported by /proc/meminfo.
|
43
47
|
# The value is in Kilobyte.
|
44
48
|
#
|
@@ -48,6 +52,7 @@ module LinuxStat
|
|
48
52
|
IO.foreach('/proc/meminfo').first(3)[-1].split[1].to_i
|
49
53
|
end
|
50
54
|
|
55
|
+
##
|
51
56
|
# Returns the amount of memory used reported by /proc/meminfo.
|
52
57
|
# The value is in Kilobyte.
|
53
58
|
#
|
@@ -58,6 +63,7 @@ module LinuxStat
|
|
58
63
|
memory[0].split[1].to_i - memory[2].split[1].to_i
|
59
64
|
end
|
60
65
|
|
66
|
+
##
|
61
67
|
# Returns the percentage of memory used reported by /proc/meminfo.
|
62
68
|
#
|
63
69
|
# It retuns an Integer but if the info is not available, it will return nil
|
@@ -68,6 +74,7 @@ module LinuxStat
|
|
68
74
|
total.-(memory[2].split[1].to_i).*(100).fdiv(total).round(2)
|
69
75
|
end
|
70
76
|
|
77
|
+
##
|
71
78
|
# Returns the percentage of memory used reported by /proc/meminfo.
|
72
79
|
#
|
73
80
|
# It retuns an Integer but if the info is not available, it will return nil
|
data/lib/linux_stat/mounts.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
module LinuxStat
|
2
2
|
module Mounts
|
3
3
|
class << self
|
4
|
-
|
4
|
+
##
|
5
|
+
# Reads /proc/mounts and returns the output splitted with \n.
|
6
|
+
#
|
7
|
+
# In other words, it's same as running IO.readlines('/proc/mounts').each(&:strip!)
|
5
8
|
#
|
6
9
|
# It returns an Array.
|
7
10
|
# If the info isn't available or /proc/mounts is not readable, it will return an empty Array.
|
@@ -9,6 +12,16 @@ module LinuxStat
|
|
9
12
|
mounts
|
10
13
|
end
|
11
14
|
|
15
|
+
##
|
16
|
+
# Reads /proc/mounts and returns list of devices.
|
17
|
+
#
|
18
|
+
# It returns an Array.
|
19
|
+
# If the info isn't available or /proc/mounts is not readable, it will return an empty Array.
|
20
|
+
def list_devices
|
21
|
+
mounts.map { |x| x.split(?\s.freeze).first }
|
22
|
+
end
|
23
|
+
|
24
|
+
##
|
12
25
|
# Reads /proc/mounts and returns partition name of the device mounted at /.
|
13
26
|
#
|
14
27
|
# It returns a String.
|
@@ -17,6 +30,7 @@ module LinuxStat
|
|
17
30
|
find_root[0].to_s
|
18
31
|
end
|
19
32
|
|
33
|
+
##
|
20
34
|
# Reads /proc/mounts and returns the file system of the device mounted at /.
|
21
35
|
#
|
22
36
|
# It returns a String.
|
@@ -25,6 +39,7 @@ module LinuxStat
|
|
25
39
|
find_root[2].to_s
|
26
40
|
end
|
27
41
|
|
42
|
+
##
|
28
43
|
# Reads /proc/mounts and returns the options used for mounting /.
|
29
44
|
#
|
30
45
|
# It returns a String.
|
@@ -33,6 +48,7 @@ module LinuxStat
|
|
33
48
|
find_root[3].to_s
|
34
49
|
end
|
35
50
|
|
51
|
+
##
|
36
52
|
# Reads /proc/mounts and finds all tmpfs.
|
37
53
|
#
|
38
54
|
# It returns a Hash
|
@@ -45,6 +61,152 @@ module LinuxStat
|
|
45
61
|
ret
|
46
62
|
end
|
47
63
|
|
64
|
+
##
|
65
|
+
# mount_point(dev = root)
|
66
|
+
#
|
67
|
+
# Where device = block device.
|
68
|
+
#
|
69
|
+
# The default argument is the root block device.
|
70
|
+
#
|
71
|
+
# It helps you find the mountpoint of a block device.
|
72
|
+
# For example:
|
73
|
+
#
|
74
|
+
# LinuxStat::Mounts.mount_point('/dev/sdb1')
|
75
|
+
#
|
76
|
+
# => "/run/media/sourav/5c2b7af7-d4c3-4ab4-a035-06d18ffc8e6f"
|
77
|
+
#
|
78
|
+
# The return type is String.
|
79
|
+
# But if the status isn't available or the device isn't mounted, it will return an empty String.
|
80
|
+
def mount_point(dev = root)
|
81
|
+
m = ''
|
82
|
+
mounts.each do |x|
|
83
|
+
x.strip!
|
84
|
+
|
85
|
+
unless x.empty?
|
86
|
+
_x = x.split
|
87
|
+
if _x[0] == dev
|
88
|
+
m.replace(_x[1])
|
89
|
+
break
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
m
|
94
|
+
end
|
95
|
+
|
96
|
+
##
|
97
|
+
# list_devices_mount_point()
|
98
|
+
#
|
99
|
+
# It shows all the block devices corresponding to mount points.
|
100
|
+
#
|
101
|
+
# For example:
|
102
|
+
#
|
103
|
+
# LinuxStat::Mounts.list_devices_mount_point
|
104
|
+
#
|
105
|
+
# => {"proc"=>"/proc", "sys"=>"/sys", "dev"=>"/dev", "run"=>"/run", "/dev/sda2"=>"/", "securityfs"=>"/sys/kernel/security", "tmpfs"=>"/run/user/1000", "devpts"=>"/dev/pts", "cgroup2"=>"/sys/fs/cgroup/unified", "cgroup"=>"/sys/fs/cgroup/perf_event", "pstore"=>"/sys/fs/pstore", "none"=>"/sys/fs/bpf", "systemd-1"=>"/proc/sys/fs/binfmt_misc", "debugfs"=>"/sys/kernel/debug", "mqueue"=>"/dev/mqueue", "hugetlbfs"=>"/dev/hugepages", "tracefs"=>"/sys/kernel/tracing", "configfs"=>"/sys/kernel/config", "fusectl"=>"/sys/fs/fuse/connections", "gvfsd-fuse"=>"/run/user/1000/gvfs", "/dev/sdb1"=>"/run/media/sourav/5c2b7af7-d4c3-4ab4-a035-06d18ffc8e6f", "binfmt_misc"=>"/proc/sys/fs/binfmt_misc"}
|
106
|
+
#
|
107
|
+
# The return type is Hash.
|
108
|
+
# But if the status isn't available or the device isn't mounted, it will return an empty String.
|
109
|
+
def list_devices_mount_point
|
110
|
+
m = {}
|
111
|
+
mounts.each do |x|
|
112
|
+
x.strip!
|
113
|
+
|
114
|
+
unless x.empty?
|
115
|
+
_x = x.split
|
116
|
+
m.merge!(_x[0] => _x[1])
|
117
|
+
end
|
118
|
+
end
|
119
|
+
m
|
120
|
+
end
|
121
|
+
|
122
|
+
##
|
123
|
+
# devices_stat
|
124
|
+
#
|
125
|
+
# [ Not to confuse this method with device_stat(dev) which shows only one device's info ]
|
126
|
+
#
|
127
|
+
# It shows all the block devices corresponding to mount points and data from LinuxStat::FS.stat(arg)
|
128
|
+
#
|
129
|
+
# For example:
|
130
|
+
#
|
131
|
+
# LinuxStat::Mounts.devices_stat
|
132
|
+
#
|
133
|
+
# => {"proc"=>{:mountpoint=>"/proc", :total=>0, :free=>0, :available=>0, :used=>0, :percent_used=>NaN, :percent_free=>NaN, :percent_available=>NaN}, "/dev/sdb1"=>{:mountpoint=>"/run/media/sourav/5c2b7af7-d4c3-4ab4-a035-06d18ffc8e6f", :total=>31466008576, :free=>2693931008, :available=>2693931008, :used=>28772077568, :percent_used=>91.44, :percent_free=>8.56, :percent_available=>8.56}}
|
134
|
+
#
|
135
|
+
# The return type is Hash.
|
136
|
+
# But if the status isn't available, it will return an empty Hash.
|
137
|
+
def devices_stat
|
138
|
+
# Code duplication is fine if it gives maximum performance
|
139
|
+
m = {}
|
140
|
+
mounts.each do |x|
|
141
|
+
x.strip!
|
142
|
+
|
143
|
+
unless x.empty?
|
144
|
+
_x = x.split
|
145
|
+
total, free, available, used = fs_info(_x[1])
|
146
|
+
|
147
|
+
m.merge!(_x[0] => {
|
148
|
+
mountpoint: _x[1],
|
149
|
+
|
150
|
+
total: total,
|
151
|
+
free: free,
|
152
|
+
available: available,
|
153
|
+
used: used,
|
154
|
+
|
155
|
+
percent_used: used.*(100).fdiv(total).round(2),
|
156
|
+
percent_free: free.*(100).fdiv(total).round(2),
|
157
|
+
percent_available: available.*(100).fdiv(total).round(2),
|
158
|
+
})
|
159
|
+
end
|
160
|
+
end
|
161
|
+
m
|
162
|
+
end
|
163
|
+
|
164
|
+
##
|
165
|
+
# device_stat(dev = root)
|
166
|
+
#
|
167
|
+
# [ Not to confuse this method with devices_stat() which shows all devices ]
|
168
|
+
#
|
169
|
+
# It shows all the block devices corresponding to mount points and data from LinuxStat::FS.stat(arg)
|
170
|
+
#
|
171
|
+
# For example:
|
172
|
+
#
|
173
|
+
# LinuxStat::Mounts.device_stat('/dev/sda2')
|
174
|
+
#
|
175
|
+
# => {"/dev/sda2"=>{:mountpoint=>"/", :total=>119981191168, :free=>35298562048, :available=>35298562048, :used=>84682629120, :percent_used=>70.58, :percent_free=>29.42, :percent_available=>29.42}}
|
176
|
+
#
|
177
|
+
# The return type is Hash.
|
178
|
+
# But if the status isn't available, it will return an empty Hash.
|
179
|
+
def device_stat(dev = root)
|
180
|
+
# Code duplication is fine if it gives maximum performance
|
181
|
+
m = {}
|
182
|
+
mounts.each do |x|
|
183
|
+
x.strip!
|
184
|
+
|
185
|
+
unless x.empty?
|
186
|
+
_x = x.split
|
187
|
+
next if _x[0] != dev
|
188
|
+
|
189
|
+
total, free, available, used = fs_info(_x[1])
|
190
|
+
|
191
|
+
m.merge!({
|
192
|
+
mountpoint: _x[1],
|
193
|
+
|
194
|
+
total: total,
|
195
|
+
free: free,
|
196
|
+
available: available,
|
197
|
+
used: used,
|
198
|
+
|
199
|
+
percent_used: used.*(100).fdiv(total).round(2),
|
200
|
+
percent_free: free.*(100).fdiv(total).round(2),
|
201
|
+
percent_available: available.*(100).fdiv(total).round(2),
|
202
|
+
})
|
203
|
+
|
204
|
+
break
|
205
|
+
end
|
206
|
+
end
|
207
|
+
m
|
208
|
+
end
|
209
|
+
|
48
210
|
private
|
49
211
|
def mount_readable?
|
50
212
|
@@mount_readable ||= File.readable?('/proc/mounts')
|
@@ -59,6 +221,19 @@ module LinuxStat
|
|
59
221
|
return [] unless mount_readable?
|
60
222
|
@@root ||= IO.foreach('/proc/mounts').find { |x| x.split[1] == '/'.freeze }.split
|
61
223
|
end
|
224
|
+
|
225
|
+
def fs_info(dev)
|
226
|
+
# => [total, free, available, used]
|
227
|
+
s = LinuxStat::FS.stat(dev)
|
228
|
+
s.default = 0
|
229
|
+
|
230
|
+
[
|
231
|
+
s[:block_size] * s[:blocks],
|
232
|
+
s[:block_size] * s[:block_free],
|
233
|
+
s[:block_size] * s[:block_avail_unpriv],
|
234
|
+
s[:blocks].-(s[:block_free]) * s[:block_size]
|
235
|
+
]
|
236
|
+
end
|
62
237
|
end
|
63
238
|
end
|
64
239
|
end
|
data/lib/linux_stat/net.rb
CHANGED
@@ -1,13 +1,131 @@
|
|
1
1
|
module LinuxStat
|
2
2
|
module Net
|
3
3
|
class << self
|
4
|
+
DEV = '/proc/net/dev'.freeze
|
5
|
+
|
6
|
+
##
|
4
7
|
# Returns the local IP address of the system as a String.
|
8
|
+
#
|
5
9
|
# If the information isn't available, it will a frozen empty string.
|
6
10
|
def ipv4_private
|
7
|
-
require 'socket'
|
11
|
+
require 'socket' unless defined?(Socket)
|
8
12
|
ip = Socket.ip_address_list.find(&:ipv4_private?)
|
9
13
|
ip ? ip.ip? ? ip.ip_unpack[0].freeze : ''.freeze : ''.freeze
|
10
14
|
end
|
15
|
+
|
16
|
+
##
|
17
|
+
# Returns the total bytes received and transmitted as Hash.
|
18
|
+
#
|
19
|
+
# For example:
|
20
|
+
# {:received=>56602867, :transmitted=>6940922}
|
21
|
+
#
|
22
|
+
# But if the status isn't available it will return an empty Hash.
|
23
|
+
def total_bytes
|
24
|
+
return {} unless File.readable?(DEV)
|
25
|
+
|
26
|
+
data = IO.readlines(DEV).drop(2)
|
27
|
+
indices = find_index_of_bytes
|
28
|
+
data.reject! { |x| x.strip.start_with?('lo:') }
|
29
|
+
r, t = data.map { |x| x.split.values_at(*indices).map(&:to_i) }.transpose.map(&:sum)
|
30
|
+
|
31
|
+
{
|
32
|
+
received: r,
|
33
|
+
transmitted: t
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
##
|
38
|
+
# Returns the total bytes received as Integer.
|
39
|
+
#
|
40
|
+
# But if the status isn't available it will return nil.
|
41
|
+
def total_bytes_received
|
42
|
+
return nil unless File.readable?(DEV)
|
43
|
+
|
44
|
+
data = IO.readlines(DEV).drop(2)
|
45
|
+
index = find_index_of_bytes[0]
|
46
|
+
data.reject! { |x| x.strip.start_with?('lo:') }
|
47
|
+
data.map { |x| x.split[index].to_i }.sum
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# Returns the total bytes transmitted as Integer.
|
52
|
+
#
|
53
|
+
# But if the status isn't available it will return nil.
|
54
|
+
def total_bytes_transmitted
|
55
|
+
return nil unless File.readable?(DEV)
|
56
|
+
|
57
|
+
data = IO.readlines(DEV).drop(2)
|
58
|
+
index = find_index_of_bytes[-1]
|
59
|
+
data.reject! { |x| x.strip.start_with?('lo:') }
|
60
|
+
data.map { |x| x.split[index].to_i }.sum
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# usage(interval = 0.1)
|
65
|
+
#
|
66
|
+
# Where interval is the time between polling in seconds. The default is 0.1 seconds.
|
67
|
+
#
|
68
|
+
# The return type is a Hash, containg the current internet usage (received, transmit) in B/s.
|
69
|
+
#
|
70
|
+
# For example:
|
71
|
+
# {:received=>436060.0, :transmitted=>50350.0}
|
72
|
+
#
|
73
|
+
# If the system transmits 100 kb in the interval,
|
74
|
+
#
|
75
|
+
# this method will return 1000 kb/s. That is, it estimates
|
76
|
+
#
|
77
|
+
# the data it will transmit in one second. Thus, a good and reliable interval is 1 second
|
78
|
+
#
|
79
|
+
# It will return an empty Hash if the info (/proc/net/dev) isn't available.
|
80
|
+
def usage(interval = 0.1)
|
81
|
+
return {} unless File.readable?(DEV)
|
82
|
+
|
83
|
+
data = IO.readlines(DEV).drop(2)
|
84
|
+
indices = find_index_of_bytes
|
85
|
+
data.reject! { |x| x.strip.start_with?('lo:') }
|
86
|
+
r, t = data.map { |x| x.split.values_at(*indices).map(&:to_i) }.transpose.map(&:sum)
|
87
|
+
|
88
|
+
sleep(interval)
|
89
|
+
|
90
|
+
data2 = IO.readlines(DEV).drop(2)
|
91
|
+
data2.reject! { |x| x.strip.start_with?('lo:') }
|
92
|
+
r2, t2 = data2.map { |x| x.split.values_at(*indices).map(&:to_i) }.transpose.map(&:sum)
|
93
|
+
|
94
|
+
# Measure the difference
|
95
|
+
dr, dt = r2.-(r).fdiv(interval), t2.-(t).fdiv(interval)
|
96
|
+
|
97
|
+
{
|
98
|
+
received: dr,
|
99
|
+
transmitted: dt
|
100
|
+
}
|
101
|
+
end
|
102
|
+
|
103
|
+
alias current_usage usage
|
104
|
+
|
105
|
+
private
|
106
|
+
# Returns the index containing the received and transmitted bytes
|
107
|
+
def find_index_of_bytes
|
108
|
+
@@index_of_bytes ||= nil
|
109
|
+
|
110
|
+
unless @@index_of_bytes
|
111
|
+
data = IO.foreach(DEV)
|
112
|
+
|
113
|
+
r, h = data.next.split, {}
|
114
|
+
|
115
|
+
r.each_with_index { |x, i|
|
116
|
+
downcased = x.downcase
|
117
|
+
h.merge!(:r => i) if downcased.start_with?('receive')
|
118
|
+
h.merge!(:t => i) if downcased.start_with?('transmit')
|
119
|
+
}
|
120
|
+
|
121
|
+
data_0 = data.next.gsub(?|.freeze, ' %'.freeze)
|
122
|
+
@@index_of_bytes = []
|
123
|
+
data_0.split.each_with_index { |x, i| @@index_of_bytes << i if x == '%bytes'.freeze }
|
124
|
+
h[:r] > h[:t] ? @@index_of_bytes.reverse : @@index_of_bytes
|
125
|
+
else
|
126
|
+
@@index_of_bytes
|
127
|
+
end
|
128
|
+
end
|
11
129
|
end
|
12
130
|
end
|
13
131
|
end
|