linux_stat 0.3.1 → 0.5.1

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.
@@ -3,7 +3,7 @@ module LinuxStat
3
3
  class << self
4
4
  # Returns the Linux Kernel version.
5
5
  # If the information isn't available, it will return a frozen empty string.
6
- # The output is also cached ; as changing the value in runtime is unexpected.
6
+ # The output is also cached (memoized) ; as changing the value in runtime is unexpected.
7
7
  def version
8
8
  return ''.freeze if string.empty?
9
9
  @@version ||= splitted[2]
@@ -11,7 +11,7 @@ module LinuxStat
11
11
 
12
12
  # Returns the name of the user who built the kernel using KBUILD_FLAGS.
13
13
  # If the information isn't available, it will return a frozen empty string.
14
- # The output is also cached ; as changing the value in runtime is unexpected.
14
+ # The output is also cached (memoized) ; as changing the value in runtime is unexpected.
15
15
  def build_user
16
16
  @@build_user ||= string.split(/(\(.+\))/).each(&:strip!)
17
17
  .reject(&:empty?).find { |x| x[/^\(.+\)$/] }.to_s
@@ -20,7 +20,7 @@ module LinuxStat
20
20
 
21
21
  # Returns the compiler used to compile the Linux Kernel.
22
22
  # If the information isn't available, it will return a frozen empty string.
23
- # The output is also cached ; as changing the value in runtime is unexpected.
23
+ # The output is also cached (memoized) ; as changing the value in runtime is unexpected.
24
24
  def compiler
25
25
  return ''.freeze if string.empty?
26
26
 
@@ -39,7 +39,7 @@ module LinuxStat
39
39
 
40
40
  # Returns the compiler version used to compile the Linux Kernel.
41
41
  # If the information isn't available, it will return a frozen empty string.
42
- # The output is also cached ; as changing the value in runtime is unexpected.
42
+ # The output is also cached (memoized) ; as changing the value in runtime is unexpected.
43
43
  def compiler_version
44
44
  @@compiler_version ||= string.split(/(\(.+?\))/).each(&:strip!)
45
45
  .reject(&:empty?)[2..4].to_a
@@ -62,7 +62,7 @@ module LinuxStat
62
62
  # You have to use regexp yourself to get the proper zone.
63
63
  # Use LinuxStat::Kernel.build_date_string to get the original string if you need that.
64
64
  #
65
- # The output is also cached ; as changing the value in runtime is unexpected.
65
+ # The output is also cached (memoized) ; as changing the value in runtime is unexpected.
66
66
  def build_date
67
67
  return nil if splitted.empty?
68
68
 
@@ -107,7 +107,7 @@ module LinuxStat
107
107
  # You have to use regexp yourself to get the proper zone.
108
108
  # Use LinuxStat::Kernel.build_date_string to get the original string if you need that.
109
109
  #
110
- # The output is also cached ; as changing the value in runtime is unexpected.
110
+ # The output is also cached (memoized) ; as changing the value in runtime is unexpected.
111
111
  def build_date_string
112
112
  return nil if splitted.empty?
113
113
 
@@ -139,6 +139,16 @@ module LinuxStat
139
139
  @@string ||= File.readable?('/proc/version') ? IO.read('/proc/version', 1024).tap(&:strip!) : ''
140
140
  end
141
141
 
142
+ # Returns the sc_clk_tck or the same output from command `getconf CLK_TCK`.
143
+ # Also, clk_tck is an alias of this method.
144
+ # The output is also cached ; as changing the value in runtime is unexpected.
145
+ def ticks
146
+ @@tick ||= LinuxStat::Sysconf.sc_clk_tck
147
+ end
148
+
149
+ alias release version
150
+ alias clk_tck ticks
151
+
142
152
  private
143
153
  def splitted
144
154
  @@string_splitted ||= string.split
@@ -2,9 +2,10 @@ module LinuxStat
2
2
  module Memory
3
3
  class << self
4
4
  # Returns the memory details reported by /proc/meminfo. In this format:
5
- # {:total=>3836264, :used=>3097952, :available=>738312, :percent_used=>80.75, :percent_available=>19.25}
5
+ # {:total=>3836264, :used=>3097952, :available=>738312, :percent_used=>80.75, :percent_available=>19.25}
6
+ #
7
+ # The values are in Kilobyte.
6
8
  #
7
- # The value is in Kilobyte.
8
9
  # If the statistics is not available, it will return an empty Hash.
9
10
  def stat
10
11
  return {} unless meminfo?
@@ -31,6 +32,7 @@ module LinuxStat
31
32
 
32
33
  # Returns the total memory details reported by /proc/meminfo.
33
34
  # The value is in Kilobyte.
35
+ #
34
36
  # It retuns an Integer but if the info is not available, it will return nil.
35
37
  def total
36
38
  return nil unless meminfo?
@@ -39,6 +41,7 @@ module LinuxStat
39
41
 
40
42
  # Returns the total memory details reported by /proc/meminfo.
41
43
  # The value is in Kilobyte.
44
+ #
42
45
  # It retuns an Integer but if the info is not available, it will return nil
43
46
  def available
44
47
  return nil unless meminfo?
@@ -47,6 +50,7 @@ module LinuxStat
47
50
 
48
51
  # Returns the amount of memory used reported by /proc/meminfo.
49
52
  # The value is in Kilobyte.
53
+ #
50
54
  # It retuns an Integer but if the info is not available, it will return nil.
51
55
  def used
52
56
  return nil unless meminfo?
@@ -55,6 +59,7 @@ module LinuxStat
55
59
  end
56
60
 
57
61
  # Returns the percentage of memory used reported by /proc/meminfo.
62
+ #
58
63
  # It retuns an Integer but if the info is not available, it will return nil
59
64
  def percent_used
60
65
  return nil unless meminfo?
@@ -64,6 +69,7 @@ module LinuxStat
64
69
  end
65
70
 
66
71
  # Returns the percentage of memory used reported by /proc/meminfo.
72
+ #
67
73
  # It retuns an Integer but if the info is not available, it will return nil
68
74
  def percent_available
69
75
  return nil unless meminfo?
@@ -2,7 +2,7 @@ module LinuxStat
2
2
  module OS
3
3
  class << self
4
4
  # Reads /etc/os-release and returns a Hash. For example:
5
- # {:NAME=>"Arch Linux", :PRETTY_NAME=>"Arch Linux", :ID=>"arch", :BUILD_ID=>"rolling", :ANSI_COLOR=>"38;2;23;147;209", :HOME_URL=>"https://www.archlinux.org/", :DOCUMENTATION_URL=>"https://wiki.archlinux.org/", :SUPPORT_URL=>"https://bbs.archlinux.org/", :BUG_REPORT_URL=>"https://bugs.archlinux.org/", :LOGO=>"archlinux"}
5
+ # {:NAME=>"Arch Linux", :PRETTY_NAME=>"Arch Linux", :ID=>"arch", :BUILD_ID=>"rolling", :ANSI_COLOR=>"38;2;23;147;209", :HOME_URL=>"https://www.archlinux.org/", :DOCUMENTATION_URL=>"https://wiki.archlinux.org/", :SUPPORT_URL=>"https://bbs.archlinux.org/", :BUG_REPORT_URL=>"https://bugs.archlinux.org/", :LOGO=>"archlinux"}
6
6
  #
7
7
  # If the info isn't available, it will return an empty Hash.
8
8
  #
@@ -11,12 +11,12 @@ module LinuxStat
11
11
  # The information is also cached, and once loaded, won't change in runtime. Because changing the /etc/lsb-release
12
12
  # isn't expected in runtime.
13
13
  def os_release
14
- # Cached ; as changing the value in runtime is unexpected
14
+ # cached (memoized) ; as changing the value in runtime is unexpected
15
15
  @@os_release ||= File.readable?('/etc/os-release') ? release('/etc/os-release') : {}
16
16
  end
17
17
 
18
18
  # Reads /etc/lsb-release and returns a Hash. For example:
19
- # {:LSB_VERSION=>"1.4", :DISTRIB_ID=>"Arch", :DISTRIB_RELEASE=>"rolling", :DISTRIB_DESCRIPTION=>"Arch Linux"}
19
+ # {:LSB_VERSION=>"1.4", :DISTRIB_ID=>"Arch", :DISTRIB_RELEASE=>"rolling", :DISTRIB_DESCRIPTION=>"Arch Linux"}
20
20
  #
21
21
  # If the info isn't available, it will return an empty Hash.
22
22
  #
@@ -25,12 +25,13 @@ module LinuxStat
25
25
  # The information is also cached, and once loaded, won't change in runtime. Because changing the /etc/lsb-release
26
26
  # isn't expected in runtime.
27
27
  def lsb_release
28
- # Cached ; as changing the value in runtime is unexpected
28
+ # cached (memoized) ; as changing the value in runtime is unexpected
29
29
  @@lsb_release ||= File.readable?('/etc/lsb-release') ? release('/etc/lsb-release') : {}
30
30
  end
31
31
 
32
32
  # Reads /etc/lsb-release or /etc/os-release tries to get information about the distribution.
33
33
  # If the information isn't available, it will read and return /etc/issue.
34
+ #
34
35
  # The return type is String.
35
36
  # If none of the info is available, it will return an empty frozen String.
36
37
  def distribution
@@ -51,7 +52,22 @@ module LinuxStat
51
52
  end
52
53
  end
53
54
 
55
+ # Uses utsname.h to determine the machine
56
+ #
57
+ # It returns a String but if the info isn't available, it will return an empty String
58
+ def machine
59
+ @@machine ||= LinuxStat::Uname.machine
60
+ end
61
+
62
+ # Uses utsname.h to determine the system nodename
63
+ #
64
+ # It returns String but if the info isn't available, it will return an empty String
65
+ def nodename
66
+ @@nodename ||= LinuxStat::Uname.nodename
67
+ end
68
+
54
69
  # Reads /etc/hostname and returns the hostname.
70
+ #
55
71
  # The return type is String.
56
72
  # If the info info isn't available, it will return 'localhost'.
57
73
  def hostname
@@ -62,10 +78,13 @@ module LinuxStat
62
78
  end
63
79
  end
64
80
 
65
- # Reads ruby configuration and tries to guess if the system is 32 bit or 64 bit.
66
- # The return type is Integer.
81
+ # Reads ruby configuration and tries to guess if the system is 64 bit.
82
+ # If it fails then it runs utsname.h to guess the machine.
83
+ # It the machine is 64 bits, it will return 64, else it returns 32.
84
+ #
85
+ # The return type is strictly Integer and doesn't fail.
67
86
  def bits
68
- @@bits ||= if RbConfig::CONFIG['host_cpu'].end_with?('64') || RUBY_PLATFORM[/x86_64/]
87
+ @@bits ||= if RbConfig::CONFIG['host_cpu'].end_with?('64') || RUBY_PLATFORM.end_with?('64') || machine.end_with?('64')
69
88
  64
70
89
  else
71
90
  32
@@ -73,7 +92,7 @@ module LinuxStat
73
92
  end
74
93
 
75
94
  # Reads /proc/uptime and returns the system uptime:
76
- # {:hour=>10, :minute=>34, :second=>12.59}
95
+ # {:hour=>10, :minute=>34, :second=>12.59}
77
96
  #
78
97
  # If the stat isn't available, an empty hash is returned.
79
98
  def uptime
@@ -0,0 +1,321 @@
1
+ module LinuxStat
2
+ module ProcessInfo
3
+ class << self
4
+ # total_io(pid = $$)
5
+ # Where pid is the process ID.
6
+ # By default it is the id of the current process ($$)
7
+ #
8
+ # It retuns the total read/write caused by a process.
9
+ # The output is Hash. For example, a sample output:
10
+ # {:read_bytes=>0, :write_bytes=>0}
11
+ #
12
+ # The output is only based on the total disk IO the process has done.
13
+ #
14
+ # If the info isn't available it will return an empty Hash.
15
+ def total_io(pid = $$)
16
+ return {} unless File.readable?("/proc/#{pid}/io".freeze)
17
+ out = {}
18
+
19
+ IO.readlines("/proc/#{pid}/io".freeze).each { |x|
20
+ x.strip!
21
+
22
+ if x[/^(read|write)_bytes:\s*\d*$/]
23
+ splitted = x.split
24
+ out.merge!(splitted[0].split(?:)[0].to_sym => splitted[-1].to_i)
25
+ end
26
+ }
27
+
28
+ out
29
+ end
30
+
31
+ # cmdline(pid = $$)
32
+ # Where pid is the process ID.
33
+ # By default it is the id of the current process ($$)
34
+ #
35
+ # It retuns the total command of the process.
36
+ # The output is String. For example, a sample output:
37
+ # "ruby -r linux_stat -e p LinuxStat::ProcessInfo.cmdline"
38
+ #
39
+ # If the info isn't available it will return an empty frozen String.
40
+ def cmdline(pid = $$)
41
+ file = "/proc/#{pid}/cmdline".freeze
42
+ return ''.freeze unless File.readable?(file)
43
+
44
+ _cmdline = IO.read(file)
45
+ _cmdline.gsub!(?\u0000, ?\s)
46
+ _cmdline.tap(&:strip!)
47
+ end
48
+
49
+ # command_name(pid = $$)
50
+ # Where pid is the process ID.
51
+ # By default it is the id of the current process ($$)
52
+ #
53
+ # It retuns the total command name of the process.
54
+ # The output is String. For example, a sample output:
55
+ # "ruby"
56
+ #
57
+ # If the info isn't available it will return an empty frozen String.
58
+ def command_name(pid = $$)
59
+ # Do note that the /proc/ppid/comm may not contain the full name
60
+ file = "/proc/#{pid}/cmdline".freeze
61
+ return ''.freeze unless File.readable?(file)
62
+
63
+ _cmdline = IO.read(file)
64
+ _cmdline.gsub!(?\u0000, ?\s)
65
+ File.split(_cmdline.tap(&:strip!).split[0])[-1]
66
+ end
67
+
68
+ # mem_stat(pid = $$)
69
+ # Where pid is the process ID.
70
+ # By default it is the id of the current process ($$)
71
+ #
72
+ # It retuns the memory, virtual memory, and resident memory of the process.
73
+ # All values are in Kilobytes.
74
+ #
75
+ # The output is a Hash. For example, a sample output:
76
+ # {:memory=>8656, :virtual_memory=>78272, :resident_memory=>14072}
77
+ #
78
+ # Note:
79
+ # If you need only memory usage of a process, run LinuxStat::ProcessInfo.memory(pid)
80
+ # If you need only virtual memory for a process, run LinuxStat::ProcessInfo.virtual_memory(pid)
81
+ # If you need only resident memory of a process, run LinuxStat::ProcessInfo.resident_memory(pid)
82
+ #
83
+ # This method opens opens multiple files.
84
+ # But if you need all of the info, then running this method once is efficient.
85
+ #
86
+ # If the info isn't available it will return an empty Hash.
87
+ def mem_stat(pid = $$)
88
+ stat_file = "/proc/#{pid}/stat".freeze
89
+ status_file = "/proc/#{pid}/status".freeze
90
+
91
+ stat = if File.readable?(stat_file)
92
+ IO.read(stat_file).split
93
+ else
94
+ []
95
+ end
96
+
97
+ status = if File.readable?(status_file)
98
+ IO.readlines(status_file)
99
+ else
100
+ []
101
+ end
102
+
103
+ _rss_anon = status.find { |x| x.start_with?('RssAnon') }
104
+ rss_anon = _rss_anon ? _rss_anon.split[1].to_i : nil
105
+
106
+ _virtual_memory = stat[22]
107
+ vm = _virtual_memory ? _virtual_memory.to_i.fdiv(1024).to_i : nil
108
+
109
+ _vm_rss = status.find { |x| x.start_with?('VmRSS') }
110
+ vm_rss = _vm_rss ? _vm_rss.split[1].to_i : nil
111
+
112
+ {
113
+ memory: rss_anon,
114
+ virtual_memory: vm,
115
+ resident_memory: vm_rss
116
+ }
117
+ end
118
+
119
+ # memory(pid = $$)
120
+ # Where pid is the process ID.
121
+ # By default it is the id of the current process ($$)
122
+ #
123
+ # It retuns the memory of the process.
124
+ # The value is in Kilobytes.
125
+ # The output is an Integer. For example, a sample output:
126
+ # 8664
127
+ #
128
+ # If the info isn't available it will return nil.
129
+ def memory(pid = $$)
130
+ file = "/proc/#{pid}/status".freeze
131
+ return nil unless File.readable?(file)
132
+
133
+ _rss_anon = IO.readlines(file).find { |x| x.start_with?('RssAnon') }
134
+ _rss_anon ? _rss_anon.split[1].to_i : nil
135
+ end
136
+
137
+ # virtual_memory(pid = $$)
138
+ # Where pid is the process ID.
139
+ # By default it is the id of the current process ($$)
140
+ #
141
+ # It retuns the virtual memory for the process.
142
+ # The value is in Kilobytes.
143
+ # The output is an Integer. For example, a sample output:
144
+ # 78376
145
+ #
146
+ # If the info isn't available it will return nil.
147
+ def virtual_memory(pid = $$)
148
+ file = "/proc/#{pid}/stat".freeze
149
+ return nil unless File.readable?(file)
150
+
151
+ _virtual_memory = IO.read(file).split[22]
152
+ _virtual_memory ? _virtual_memory.to_i.fdiv(1024).to_i : nil
153
+ end
154
+
155
+ # resident_memory(pid = $$)
156
+ # Where pid is the process ID.
157
+ # By default it is the id of the current process ($$)
158
+ #
159
+ # It retuns the resident memory for the process.
160
+ # The value is in Kilobytes.
161
+ # The output is an Integer. For example, a sample output:
162
+ # 14012
163
+ #
164
+ # If the info isn't available it will return nil.
165
+ def resident_memory(pid = $$)
166
+ file = "/proc/#{pid}/status".freeze
167
+ return nil unless File.readable?(file)
168
+
169
+ _vm_rss = IO.readlines(file)
170
+ .find { |x| x.start_with?('VmRSS') }
171
+
172
+ _vm_rss ? _vm_rss.split[1].to_i : nil
173
+ end
174
+
175
+ # cpu_stat(pid: $$, sleep: 0.05)
176
+ # Where pid is the process ID and sleep time is the interval between measurements.
177
+ # By default it is the id of the current process ($$), and sleep is 0.05
178
+ #
179
+ # Note 1:
180
+ # Do note that the sleep time can slow down your application.
181
+ # And it's only needed for the cpu usage calculation.
182
+ #
183
+ # It retuns the CPU usage, threads, and the last executed CPU in Hash.
184
+ # For example:
185
+ # {:cpu_usage=>0.0, :threads=>1, :last_executed_cpu=>1}
186
+ #
187
+ # But if the info isn't available, it will return an empty Hash.
188
+ #
189
+ # The :cpu_usage is in percentage. It's also divided with the number
190
+ # of CPU. :cpu_usage for example, will return 25.0 if the CPU count
191
+ # is 4, and the process is using 100% of a thread / core.
192
+ # A value of 100.0 indicates it is using 100% processing power.
193
+ #
194
+ # The :threads returns the number of threads for the process.
195
+ # The value is a Integer.
196
+ #
197
+ # Note 2:
198
+ # If you just need the CPU usage run LinuxStat::ProcessInfo.cpu_usage(pid = $$)
199
+ # If you just need the threads run LinuxStat::ProcessInfo.threads(pid = $$)
200
+ # If you just need the last executed CPU run LinuxStat::ProcessInfo.last_executed_cpu(pid = $$)
201
+ # Running this method is slower and it opens multiple files at once
202
+ #
203
+ # Only use this method if you need all of the data at once, in such case, it's more efficient to use this method.
204
+ #
205
+ # The :last_executed_cpu also returns an Integer indicating
206
+ # the last executed cpu of the process.
207
+ def cpu_stat(pid: $$, sleep: 0.05)
208
+ file = "/proc/#{pid}/stat"
209
+ return {} unless File.readable?(file)
210
+
211
+ ticks = get_ticks
212
+
213
+ utime, stime, starttime = IO.read(file)
214
+ .split.values_at(13, 14, 21).map(&:to_f)
215
+ uptime = IO.read('/proc/uptime'.freeze).to_f * ticks
216
+
217
+ total_time = utime + stime
218
+ idle1 = uptime - starttime - total_time
219
+
220
+ sleep(sleep)
221
+ stat = IO.read(file).split
222
+
223
+ utime2, stime2, starttime2 = stat.values_at(13, 14, 21).map(&:to_f)
224
+ uptime = IO.read('/proc/uptime'.freeze).to_f * ticks
225
+
226
+ total_time2 = utime2 + stime2
227
+ idle2 = uptime - starttime2 - total_time2
228
+
229
+ totald = idle2.+(total_time2).-(idle1 + total_time)
230
+ cpu = totald.-(idle2 - idle1).fdiv(totald).*(100).round(2).abs./(LinuxStat::CPU.count)
231
+
232
+ {
233
+ cpu_usage: cpu,
234
+ threads: stat[19].to_i,
235
+ last_executed_cpu: stat[38].to_i
236
+ }
237
+ end
238
+
239
+ # cpu_usage(pid: $$, sleep: 0.05)
240
+ # Where pid is the process ID and sleep time is the interval between measurements.
241
+ # By default it is the id of the current process ($$), and sleep is 0.05
242
+ #
243
+ # It retuns the CPU usage in Float.
244
+ # For example:
245
+ # 10.0
246
+ # A value of 100.0 indicates it is using 100% processing power.
247
+ #
248
+ # But if the info isn't available, it will return nil.
249
+ #
250
+ # This method is more efficient than running LinuxStat::ProcessInfo.cpu_stat()
251
+ def cpu_usage(pid: $$, sleep: 0.05)
252
+ file = "/proc/#{pid}/stat"
253
+ return nil unless File.readable?(file)
254
+
255
+ ticks = get_ticks
256
+
257
+ utime, stime, starttime = IO.read(file)
258
+ .split.values_at(13, 14, 21).map(&:to_f)
259
+ uptime = IO.read('/proc/uptime'.freeze).to_f * ticks
260
+
261
+ total_time = utime + stime
262
+ idle1 = uptime - starttime - total_time
263
+
264
+ sleep(sleep)
265
+
266
+ utime2, stime2, starttime2 = IO.read(file)
267
+ .split.values_at(13, 14, 21).map(&:to_f)
268
+ uptime = IO.read('/proc/uptime'.freeze).to_f * ticks
269
+
270
+ total_time2 = utime2 + stime2
271
+ idle2 = uptime - starttime2 - total_time2
272
+
273
+ totald = idle2.+(total_time2).-(idle1 + total_time)
274
+ totald.-(idle2 - idle1).fdiv(totald).*(100).round(2).abs./(LinuxStat::CPU.count)
275
+ end
276
+
277
+ # threads(pid = $$)
278
+ # Where pid is the process ID.
279
+ # By default it is the id of the current process ($$)
280
+ #
281
+ # It retuns the threads for the current process in Integer.
282
+ # For example:
283
+ # 1
284
+ # But if the info isn't available, it will return nil.
285
+ #
286
+ # This method is way more efficient than running LinuxStat::ProcessInfo.cpu_stat()
287
+ def threads(pid = $$)
288
+ file = "/proc/#{pid}/stat".freeze
289
+ return nil unless File.readable?(file)
290
+
291
+ IO.read(file).split[19].to_i
292
+ end
293
+
294
+ # last_executed_cpu(pid = $$)
295
+ # Where pid is the process ID.
296
+ # By default it is the id of the current process ($$)
297
+ #
298
+ # It retuns the last executed CPU in Integer.
299
+ # For example:
300
+ # 2
301
+ # But if the info isn't available, it will return nil.
302
+ #
303
+ # This method is way more efficient than running LinuxStat::ProcessInfo.cpu_stat()
304
+ def last_executed_cpu(pid = $$)
305
+ file = "/proc/#{pid}/stat".freeze
306
+ return nil unless File.readable?(file)
307
+
308
+ IO.read("/proc/#{pid}/stat".freeze).split[38].to_i
309
+ end
310
+
311
+ # def owned_by
312
+
313
+ # end
314
+
315
+ private
316
+ def get_ticks
317
+ @@ticks ||= Sysconf.sc_clk_tck
318
+ end
319
+ end
320
+ end
321
+ end