tddium-sys-proctable 0.9.2-x86-linux

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.
@@ -0,0 +1,21 @@
1
+ ########################################################################
2
+ # bench_ps.rb
3
+ #
4
+ # Benchmark program to show overall speed and compare the block form
5
+ # versus the non-block form. You should run this benchmark via the
6
+ # 'rake bench' Rake task.
7
+ ########################################################################
8
+ require 'benchmark'
9
+ require 'sys/proctable'
10
+
11
+ MAX = 10
12
+
13
+ Benchmark.bm do |bench|
14
+ bench.report("Block form"){
15
+ MAX.times{ Sys::ProcTable.ps{} }
16
+ }
17
+
18
+ bench.report("Non-block form"){
19
+ MAX.times{ Sys::ProcTable.ps }
20
+ }
21
+ end
data/doc/top.txt ADDED
@@ -0,0 +1,47 @@
1
+ = Description
2
+ A simple 'top' interface for Ruby
3
+
4
+ = Prerequisites
5
+ Requires the "sys/proctable" package (which should be installed along
6
+ with this package).
7
+
8
+ = Synopsis
9
+ require "sys/top"
10
+
11
+ Sys::Top.top(5).each{ |ps|
12
+ p ps
13
+ }
14
+
15
+ = Constants
16
+ VERSION
17
+ Returns the version number of this package as a String.
18
+
19
+ = Class Methods
20
+ Sys::Top.top(number=10, field="pctcpu")
21
+ Returns an array of ProcTableStruct's. The size of the array (i.e. the
22
+ number of processes) that it returns is based on +number+, and sorted by
23
+ +pctcpu+. By default, the size and field values are 10 and "pctcpu",
24
+ respectively.
25
+
26
+ = Notes
27
+ Not all fields are available on all platforms. Please check your
28
+ platform specific documentation for which fields are available.
29
+
30
+ = Bugs
31
+ None that I'm aware of. Please log bug reports on the project page at
32
+ http://www.rubyforge.org/projects/sysutils
33
+
34
+ = License
35
+ Artistic 2.0
36
+
37
+ = Copyright
38
+ (C) 2004-2009 Daniel J. Berger
39
+ All Rights Reserved.
40
+
41
+ = Warranty
42
+ This package is provided "as is" and without any express or
43
+ implied warranties, including, without limitation, the implied
44
+ warranties of merchantability and fitness for a particular purpose.
45
+
46
+ = Author
47
+ Daniel J. Berger
@@ -0,0 +1,20 @@
1
+ #######################################################################
2
+ # example_ps.rb
3
+ #
4
+ # Generic test program that demonstrates the use of ProcTable.ps. You
5
+ # can run this via the 'rake example' task.
6
+ #
7
+ # Modify as you see fit
8
+ #######################################################################
9
+ require 'sys/proctable'
10
+ include Sys
11
+
12
+ puts "VERSION: " + ProcTable::VERSION
13
+ sleep 2
14
+
15
+ ProcTable.ps{ |s|
16
+ ProcTable.fields.each{ |field|
17
+ puts "#{field}: " + s.send(field).to_s
18
+ }
19
+ puts '=' * 30
20
+ }
@@ -0,0 +1,281 @@
1
+ # The Sys module serves as a namespace only.
2
+ module Sys
3
+
4
+ # The ProcTable class encapsulates process table information.
5
+ class ProcTable
6
+
7
+ # Error typically raised if the ProcTable.ps method fails.
8
+ class Error < StandardError; end
9
+
10
+ # There is no constructor
11
+ private_class_method :new
12
+
13
+ # The version of the sys-proctable library
14
+ VERSION = '0.9.1'
15
+
16
+ private
17
+
18
+ @mem_total = IO.read("/proc/meminfo")[/MemTotal.*/].split[1].to_i * 1024 rescue nil
19
+ @boot_time = IO.read("/proc/stat")[/btime.*/].split.last.to_i rescue nil
20
+
21
+ @fields = [
22
+ 'cmdline', # Complete command line
23
+ 'cwd', # Current working directory
24
+ 'environ', # Environment
25
+ 'exe', # Actual pathname of the executed command
26
+ 'fd', # File descriptors open by process
27
+ 'root', # Root directory of process
28
+ 'pid', # Process ID
29
+ 'comm', # Filename of executable
30
+ 'state', # Single character state abbreviation
31
+ 'ppid', # Parent process ID
32
+ 'pgrp', # Process group
33
+ 'session', # Session ID
34
+ 'tty_nr', # TTY (terminal) associated with the process
35
+ 'tpgid', # Group ID of the TTY
36
+ 'flags', # Kernel flags
37
+ 'minflt', # Number of minor faults
38
+ 'cminflt', # Number of minor faults of waited-for children
39
+ 'majflt', # Number of major faults
40
+ 'cmajflt', # Number of major faults of waited-for children
41
+ 'utime', # Number of user mode jiffies
42
+ 'stime', # Number of kernel mode jiffies
43
+ 'cutime', # Number of children's user mode jiffies
44
+ 'cstime', # Number of children's kernel mode jiffies
45
+ 'priority', # Nice value plus 15
46
+ 'nice', # Nice value
47
+ 'itrealvalue', # Time in jiffies before next SIGALRM
48
+ 'starttime', # Time in jiffies since system boot
49
+ 'vsize', # Virtual memory size in bytes
50
+ 'rss', # Resident set size
51
+ 'rlim', # Current limit on the rss in bytes
52
+ 'startcode', # Address above which program text can run
53
+ 'endcode', # Address below which program text can run
54
+ 'startstack', # Address of the startstack
55
+ 'kstkesp', # Kernel stack page address
56
+ 'kstkeip', # Kernel instruction pointer
57
+ 'signal', # Bitmap of pending signals
58
+ 'blocked', # Bitmap of blocked signals
59
+ 'sigignore', # Bitmap of ignored signals
60
+ 'sigcatch', # Bitmap of caught signals
61
+ 'wchan', # Channel in which the process is waiting
62
+ 'nswap', # Number of pages swapped
63
+ 'cnswap', # Cumulative nswap for child processes
64
+ 'exit_signal', # Signal to be sent to parent when process dies
65
+ 'processor', # CPU number last executed on
66
+ 'rt_priority', # Real time scheduling priority
67
+ 'policy', # Scheduling policy
68
+ 'name', # Process name
69
+ 'uid', # Real user ID
70
+ 'euid', # Effective user ID
71
+ 'gid', # Real group ID
72
+ 'egid', # Effective group ID
73
+ 'pctcpu', # Percent of CPU usage (custom field)
74
+ 'pctmem' # Percent of Memory usage (custom field)
75
+ ]
76
+
77
+ public
78
+
79
+ ProcTableStruct = Struct.new('ProcTableStruct', *@fields)
80
+
81
+ # In block form, yields a ProcTableStruct for each process entry that you
82
+ # have rights to. This method returns an array of ProcTableStruct's in
83
+ # non-block form.
84
+ #
85
+ # If a +pid+ is provided, then only a single ProcTableStruct is yielded or
86
+ # returned, or nil if no process information is found for that +pid+.
87
+ #
88
+ # Example:
89
+ #
90
+ # # Iterate over all processes
91
+ # ProcTable.ps do |proc_info|
92
+ # p proc_info
93
+ # end
94
+ #
95
+ # # Print process table information for only pid 1001
96
+ # p ProcTable.ps(1001)
97
+ #
98
+ #--
99
+ # It's possible that a process could terminate while gathering
100
+ # information for that process. When that happens, this library
101
+ # will simply skip to the next record. In short, this library will
102
+ # either return all information for a process, or none at all.
103
+ #
104
+ def self.ps(pid=nil)
105
+ array = block_given? ? nil : []
106
+ struct = nil
107
+
108
+ raise TypeError unless pid.is_a?(Fixnum) if pid
109
+
110
+ Dir.foreach("/proc"){ |file|
111
+ next if file =~ /\D/ # Skip non-numeric directories
112
+ next unless file.to_i == pid if pid
113
+
114
+ struct = ProcTableStruct.new
115
+
116
+ # Get /proc/<pid>/cmdline information. Strip out embedded nulls.
117
+ begin
118
+ data = IO.read("/proc/#{file}/cmdline").tr("\000", ' ').strip
119
+ struct.cmdline = data
120
+ rescue
121
+ next # Process terminated, on to the next process
122
+ end
123
+
124
+ # Get /proc/<pid>/cwd information
125
+ struct.cwd = File.readlink("/proc/#{file}/cwd") rescue nil
126
+
127
+ # Get /proc/<pid>/environ information. Environment information
128
+ # is represented as a Hash, with the environment variable as the
129
+ # key and its value as the hash value.
130
+ struct.environ = {}
131
+
132
+ begin
133
+ IO.read("/proc/#{file}/environ").split("\0").each{ |str|
134
+ key, value = str.split('=')
135
+ struct.environ[key] = value
136
+ }
137
+ rescue Errno::EACCES
138
+ # Ignore and move on.
139
+ end
140
+
141
+ # Get /proc/<pid>/exe information
142
+ struct.exe = File.readlink("/proc/#{file}/exe") rescue nil
143
+
144
+ # Get /proc/<pid>/fd information. File descriptor information
145
+ # is represented as a Hash, with the fd as the key, and its
146
+ # symlink as the value.
147
+ struct.fd = {}
148
+
149
+ begin
150
+ Dir["/proc/#{file}/fd/*"].each do |fd|
151
+ struct.fd[File.basename(fd)] = File.readlink(fd) rescue nil
152
+ end
153
+ rescue
154
+ # Ignore and move on
155
+ end
156
+
157
+ # Get /proc/<pid>/root information
158
+ struct.root = File.readlink("/proc/#{file}/root") rescue nil
159
+
160
+ # Get /proc/<pid>/stat information
161
+ stat = IO.read("/proc/#{file}/stat") rescue next
162
+
163
+ # Deal with spaces in comm name. Courtesy of Ara Howard.
164
+ re = %r/\([^\)]+\)/
165
+ comm = stat[re]
166
+ comm.tr!(' ', '-')
167
+ stat[re] = comm
168
+
169
+ stat = stat.split
170
+
171
+ struct.pid = stat[0].to_i
172
+ struct.comm = stat[1].tr('()','') # Remove parens
173
+ struct.state = stat[2]
174
+ struct.ppid = stat[3].to_i
175
+ struct.pgrp = stat[4].to_i
176
+ struct.session = stat[5].to_i
177
+ struct.tty_nr = stat[6].to_i
178
+ struct.tpgid = stat[7].to_i
179
+ struct.flags = stat[8].to_i
180
+ struct.minflt = stat[9].to_i
181
+ struct.cminflt = stat[10].to_i
182
+ struct.majflt = stat[11].to_i
183
+ struct.cmajflt = stat[12].to_i
184
+ struct.utime = stat[13].to_i
185
+ struct.stime = stat[14].to_i
186
+ struct.cutime = stat[15].to_i
187
+ struct.cstime = stat[16].to_i
188
+ struct.priority = stat[17].to_i
189
+ struct.nice = stat[18].to_i
190
+ # Skip 19
191
+ struct.itrealvalue = stat[20].to_i
192
+ struct.starttime = stat[21].to_i
193
+ struct.vsize = stat[22].to_i
194
+ struct.rss = stat[23].to_i
195
+ struct.rlim = stat[24].to_i
196
+ struct.startcode = stat[25].to_i
197
+ struct.endcode = stat[26].to_i
198
+ struct.startstack = stat[27].to_i
199
+ struct.kstkesp = stat[28].to_i
200
+ struct.kstkeip = stat[29].to_i
201
+ struct.signal = stat[30].to_i
202
+ struct.blocked = stat[31].to_i
203
+ struct.sigignore = stat[32].to_i
204
+ struct.sigcatch = stat[33].to_i
205
+ struct.wchan = stat[34].to_i
206
+ struct.nswap = stat[35].to_i
207
+ struct.cnswap = stat[36].to_i
208
+ struct.exit_signal = stat[37].to_i
209
+ struct.processor = stat[38].to_i
210
+ struct.rt_priority = stat[39].to_i
211
+ struct.policy = stat[40].to_i
212
+
213
+ # Get /proc/<pid>/status information (name, uid, euid, gid, egid)
214
+ IO.foreach("/proc/#{file}/status") do |line|
215
+ case line
216
+ when /Name:\s*?(\w+)/
217
+ struct.name = $1
218
+ when /Uid:\s*?(\d+)\s*?(\d+)/
219
+ struct.uid = $1.to_i
220
+ struct.euid = $2.to_i
221
+ when /Gid:\s*?(\d+)\s*?(\d+)/
222
+ struct.gid = $1.to_i
223
+ struct.egid = $2.to_i
224
+ end
225
+ end
226
+
227
+ # If cmdline is empty use comm instead
228
+ struct.cmdline = struct.comm if struct.cmdline.empty?
229
+
230
+ # Manually calculate CPU and memory usage
231
+ struct.pctcpu = get_pctcpu(struct.utime, struct.starttime)
232
+ struct.pctmem = get_pctmem(struct.rss)
233
+
234
+ struct.freeze # This is read-only data
235
+
236
+ if block_given?
237
+ yield struct
238
+ else
239
+ array << struct
240
+ end
241
+ }
242
+
243
+ pid ? struct : array
244
+ end
245
+
246
+ # Returns an array of fields that each ProcTableStruct will contain. This
247
+ # may be useful if you want to know in advance what fields are available
248
+ # without having to perform at least one read of the /proc table.
249
+ #
250
+ # Example:
251
+ #
252
+ # Sys::ProcTable.fields.each{ |field|
253
+ # puts "Field: #{field}"
254
+ # }
255
+ #
256
+ def self.fields
257
+ @fields
258
+ end
259
+
260
+ private
261
+
262
+ # Calculate the percentage of memory usage for the given process.
263
+ #
264
+ def self.get_pctmem(rss)
265
+ return nil unless @mem_total
266
+ page_size = 4096
267
+ rss_total = rss * page_size
268
+ sprintf("%3.2f", (rss_total.to_f / @mem_total) * 100).to_f
269
+ end
270
+
271
+ # Calculate the percentage of CPU usage for the given process.
272
+ #
273
+ def self.get_pctcpu(utime, start_time)
274
+ return nil unless @boot_time
275
+ hertz = 100.0
276
+ utime = (utime * 10000).to_f
277
+ stime = (start_time.to_f / hertz) + @boot_time
278
+ sprintf("%3.2f", (utime / 10000.0) / (Time.now.to_i - stime)).to_f
279
+ end
280
+ end
281
+ end
data/lib/sys/top.rb ADDED
@@ -0,0 +1,32 @@
1
+ require 'sys/proctable'
2
+ require 'rbconfig'
3
+
4
+ # The Sys module serves as a namespace only
5
+ module Sys
6
+
7
+ # The Top class serves as a toplevel name for the 'top' method.
8
+ class Top
9
+
10
+ # The version of the sys-top library
11
+ VERSION = '1.0.3'
12
+
13
+ # Returns an array of Struct::ProcTableStruct elements containing up
14
+ # to +num+ elements, sorted by +field+. The default number of elements
15
+ # is 10, while the default field is 'pctcpu'.
16
+ #
17
+ # Exception: the default sort field is 'pid' on Linux and Windows.
18
+ #
19
+ def self.top(num=10, field='pctcpu')
20
+ field = field.to_s if field.is_a?(Symbol)
21
+
22
+ windows = /mswin|win32|windows|dos|cygwin|mingw/i
23
+
24
+ # Sort by pid on Windows by default
25
+ if Config::CONFIG['host_os'].match(windows) && field == 'pctcpu'
26
+ field = 'pid'
27
+ end
28
+
29
+ Sys::ProcTable.ps.sort_by{ |obj| obj.send(field) || '' }[0..num-1]
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,42 @@
1
+ require 'rubygems'
2
+ require 'rbconfig'
3
+
4
+ Gem::Specification.new do |spec|
5
+ spec.name = 'tddium-sys-proctable'
6
+ spec.version = '0.9.2'
7
+ spec.author = 'Daniel J. Berger'
8
+ spec.license = 'Artistic 2.0'
9
+ spec.email = 'info@tddium.com'
10
+ spec.homepage = 'http://www.rubyforge.org/projects/sysutils'
11
+ spec.platform = Gem::Platform::CURRENT
12
+ spec.summary = 'An interface for providing process table information'
13
+ spec.has_rdoc = true
14
+ spec.test_files = ['test/test_sys_proctable_all.rb']
15
+
16
+ # Additional files for your platform are added by the 'rake gem' task.
17
+ spec.files = [
18
+ 'benchmarks/bench_ps.rb',
19
+ 'examples/example_ps.rb',
20
+ 'lib/sys/top.rb',
21
+ 'CHANGES',
22
+ 'MANIFEST',
23
+ 'Rakefile',
24
+ 'README',
25
+ 'sys-proctable.gemspec'
26
+ ]
27
+
28
+ spec.rubyforge_project = 'sysutils'
29
+ spec.extra_rdoc_files = ['CHANGES', 'README', 'MANIFEST', 'doc/top.txt']
30
+
31
+ spec.add_development_dependency('test-unit', '>= 2.1.2')
32
+
33
+ spec.description = <<-EOF
34
+ Testing a separate publish to see if I can get the mac install to work with bundler.
35
+
36
+ The sys-proctable library provides an interface for gathering information
37
+ about processes on your system, i.e. the process table. Most major
38
+ platforms are supported and, while different platforms may return
39
+ different information, the external interface is identical across
40
+ platforms.
41
+ EOF
42
+ end