linux_stat 0.3.0 → 0.4.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.
@@ -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
 
@@ -133,12 +133,23 @@ module LinuxStat
133
133
  end
134
134
  end
135
135
 
136
+ alias release version
137
+
136
138
  # Reads maximum 1024 bytes from /proc/version and returns the string.
137
139
  # The output is also cached ; as changing the value in runtime is unexpected.
138
140
  def string
139
141
  @@string ||= File.readable?('/proc/version') ? IO.read('/proc/version', 1024).tap(&:strip!) : ''
140
142
  end
141
143
 
144
+ # Returns the sc_clk_tck or the same output from command `getconf CLK_TCK`.
145
+ # Also, clk_tck is an alias of this method.
146
+ # The output is also cached ; as changing the value in runtime is unexpected.
147
+ def ticks
148
+ @@tick ||= LinuxStat::Sysconf.sc_clk_tck
149
+ end
150
+
151
+ alias clk_tck ticks
152
+
142
153
  private
143
154
  def splitted
144
155
  @@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,310 @@
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
+ _rss_anon = IO.readlines("/proc/#{pid}/status")
131
+ .find { |x| x.start_with?('RssAnon') }
132
+
133
+ _rss_anon ? _rss_anon.split[1].to_i : nil
134
+ end
135
+
136
+ # virtual_memory(pid = $$)
137
+ # Where pid is the process ID.
138
+ # By default it is the id of the current process ($$)
139
+ #
140
+ # It retuns the virtual memory for the process.
141
+ # The value is in Kilobytes.
142
+ # The output is an Integer. For example, a sample output:
143
+ # 78376
144
+ #
145
+ # If the info isn't available it will return nil.
146
+ def virtual_memory(pid = $$)
147
+ _virtual_memory = IO.read("/proc/#{pid}/stat".freeze).split[22]
148
+ _virtual_memory ? _virtual_memory.to_i.fdiv(1024).to_i : nil
149
+ end
150
+
151
+ # resident_memory(pid = $$)
152
+ # Where pid is the process ID.
153
+ # By default it is the id of the current process ($$)
154
+ #
155
+ # It retuns the resident memory for the process.
156
+ # The value is in Kilobytes.
157
+ # The output is an Integer. For example, a sample output:
158
+ # 14012
159
+ #
160
+ # If the info isn't available it will return nil.
161
+ def resident_memory(pid = $$)
162
+ _vm_rss = IO.readlines("/proc/#{pid}/status")
163
+ .find { |x| x.start_with?('VmRSS') }
164
+
165
+ _vm_rss ? _vm_rss.split[1].to_i : nil
166
+ end
167
+
168
+ # cpu_stat(pid: $$, sleep: 0.05)
169
+ # Where pid is the process ID and sleep time is the interval between measurements.
170
+ # By default it is the id of the current process ($$), and sleep is 0.05
171
+ #
172
+ # Note 1:
173
+ # Do note that the sleep time can slow down your application.
174
+ # And it's only needed for the cpu usage calculation.
175
+ #
176
+ # It retuns the CPU usage, threads, and the last executed CPU in Hash.
177
+ # For example:
178
+ # {:cpu_usage=>0.0, :threads=>1, :last_executed_cpu=>1}
179
+ #
180
+ # But if the info isn't available, it will return an empty Hash.
181
+ #
182
+ # The :cpu_usage is in percentage. It's also divided with the number
183
+ # of CPU. :cpu_usage for example, will return 25.0 if the CPU count
184
+ # is 4, and the process is using 100% of a thread / core.
185
+ # A value of 100.0 indicates it is using 100% processing power.
186
+ #
187
+ # The :threads returns the number of threads for the process.
188
+ # The value is a Integer.
189
+ #
190
+ # Note 2:
191
+ # If you just need the CPU usage run LinuxStat::ProcessInfo.cpu_usage(pid = $$)
192
+ # If you just need the threads run LinuxStat::ProcessInfo.threads(pid = $$)
193
+ # If you just need the last executed CPU run LinuxStat::ProcessInfo.last_executed_cpu(pid = $$)
194
+ # Running this method is slower and it opens multiple files at once
195
+ #
196
+ # Only use this method if you need all of the data at once, in such case, it's more efficient to use this method.
197
+ #
198
+ # The :last_executed_cpu also returns an Integer indicating
199
+ # the last executed cpu of the process.
200
+ def cpu_stat(pid: $$, sleep: 0.05)
201
+ file = "/proc/#{pid}/stat"
202
+ return {} unless File.readable?(file)
203
+
204
+ ticks = get_ticks
205
+
206
+ utime, stime, starttime = IO.read(file)
207
+ .split.values_at(13, 14, 21).map(&:to_f)
208
+ uptime = IO.read('/proc/uptime'.freeze).to_f * ticks
209
+
210
+ total_time = utime + stime
211
+ idle1 = uptime - starttime - total_time
212
+
213
+ sleep(sleep)
214
+ stat = IO.read(file).split
215
+
216
+ utime2, stime2, starttime2 = stat.values_at(13, 14, 21).map(&:to_f)
217
+ uptime = IO.read('/proc/uptime'.freeze).to_f * ticks
218
+
219
+ total_time2 = utime2 + stime2
220
+ idle2 = uptime - starttime2 - total_time2
221
+
222
+ totald = idle2.+(total_time2).-(idle1 + total_time)
223
+ cpu = totald.-(idle2 - idle1).fdiv(totald).*(100).round(2).abs./(LinuxStat::CPU.count)
224
+
225
+ {
226
+ cpu_usage: cpu,
227
+ threads: stat[19].to_i,
228
+ last_executed_cpu: stat[38].to_i
229
+ }
230
+ end
231
+
232
+ # cpu_usage(pid: $$, sleep: 0.05)
233
+ # Where pid is the process ID and sleep time is the interval between measurements.
234
+ # By default it is the id of the current process ($$), and sleep is 0.05
235
+ #
236
+ # It retuns the CPU usage in Float.
237
+ # For example:
238
+ # 10.0
239
+ # A value of 100.0 indicates it is using 100% processing power.
240
+ #
241
+ # But if the info isn't available, it will return nil.
242
+ #
243
+ # This method is more efficient than running LinuxStat::ProcessInfo.cpu_stat()
244
+ def cpu_usage(pid: $$, sleep: 0.05)
245
+ file = "/proc/#{pid}/stat"
246
+ return nil unless File.readable?(file)
247
+
248
+ ticks = get_ticks
249
+
250
+ utime, stime, starttime = IO.read(file)
251
+ .split.values_at(13, 14, 21).map(&:to_f)
252
+ uptime = IO.read('/proc/uptime'.freeze).to_f * ticks
253
+
254
+ total_time = utime + stime
255
+ idle1 = uptime - starttime - total_time
256
+
257
+ sleep(sleep)
258
+
259
+ utime2, stime2, starttime2 = IO.read(file)
260
+ .split.values_at(13, 14, 21).map(&:to_f)
261
+ uptime = IO.read('/proc/uptime'.freeze).to_f * ticks
262
+
263
+ total_time2 = utime2 + stime2
264
+ idle2 = uptime - starttime2 - total_time2
265
+
266
+ totald = idle2.+(total_time2).-(idle1 + total_time)
267
+ totald.-(idle2 - idle1).fdiv(totald).*(100).round(2).abs./(LinuxStat::CPU.count)
268
+ end
269
+
270
+ # threads(pid = $$)
271
+ # Where pid is the process ID.
272
+ # By default it is the id of the current process ($$)
273
+ #
274
+ # It retuns the threads for the current process in Integer.
275
+ # For example:
276
+ # 1
277
+ # But if the info isn't available, it will return nil.
278
+ #
279
+ # This method is way more efficient than running LinuxStat::ProcessInfo.cpu_stat()
280
+ def threads(pid = $$)
281
+ file = "/proc/#{pid}/stat".freeze
282
+ return nil unless File.readable?(file)
283
+
284
+ IO.read(file).split[19].to_i
285
+ end
286
+
287
+ # last_executed_cpu(pid = $$)
288
+ # Where pid is the process ID.
289
+ # By default it is the id of the current process ($$)
290
+ #
291
+ # It retuns the last executed CPU in Integer.
292
+ # For example:
293
+ # 2
294
+ # But if the info isn't available, it will return nil.
295
+ #
296
+ # This method is way more efficient than running LinuxStat::ProcessInfo.cpu_stat()
297
+ def last_executed_cpu(pid = $$)
298
+ file = "/proc/#{pid}/stat".freeze
299
+ return nil unless File.readable?(file)
300
+
301
+ IO.read("/proc/#{pid}/stat".freeze).split[38].to_i
302
+ end
303
+
304
+ private
305
+ def get_ticks
306
+ @@ticks ||= Sysconf.sc_clk_tck
307
+ end
308
+ end
309
+ end
310
+ end