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.
@@ -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
- # It will match any date matching any of these formats:
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
- # It will match any date matching any of these formats:
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
@@ -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
@@ -1,7 +1,10 @@
1
1
  module LinuxStat
2
2
  module Mounts
3
3
  class << self
4
- # Reads /proc/mounts and returns list of devices.
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
@@ -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