sys-proctable 0.7.6 → 1.2.0
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 +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +1 -0
- data/CHANGES +165 -0
- data/MANIFEST +33 -41
- data/README +115 -135
- data/Rakefile +94 -0
- data/benchmarks/bench_ps.rb +21 -0
- data/doc/top.txt +5 -11
- data/examples/example_ps.rb +20 -0
- data/lib/aix/sys/proctable.rb +458 -0
- data/lib/darwin/sys/proctable.rb +363 -0
- data/lib/freebsd/sys/proctable.rb +363 -0
- data/lib/linux/sys/proctable.rb +314 -0
- data/lib/linux/sys/proctable/cgroup_entry.rb +50 -0
- data/lib/linux/sys/proctable/smaps.rb +118 -0
- data/lib/sunos/sys/proctable.rb +456 -0
- data/lib/sys-proctable.rb +1 -0
- data/lib/sys-top.rb +1 -0
- data/lib/sys/proctable.rb +18 -0
- data/lib/sys/proctable/version.rb +6 -0
- data/lib/sys/top.rb +28 -19
- data/lib/windows/sys/proctable.rb +208 -0
- data/spec/sys_proctable_aix_spec.rb +328 -0
- data/spec/sys_proctable_all_spec.rb +89 -0
- data/spec/sys_proctable_darwin_spec.rb +120 -0
- data/spec/sys_proctable_freebsd_spec.rb +210 -0
- data/spec/sys_proctable_linux_spec.rb +310 -0
- data/spec/sys_proctable_sunos_spec.rb +316 -0
- data/spec/sys_proctable_windows_spec.rb +317 -0
- data/spec/sys_top_spec.rb +51 -0
- data/sys-proctable.gemspec +38 -0
- metadata +140 -64
- metadata.gz.sig +0 -0
- data/doc/freebsd.txt +0 -90
- data/doc/hpux.txt +0 -77
- data/doc/linux.txt +0 -85
- data/doc/solaris.txt +0 -99
- data/doc/windows.txt +0 -122
- data/ext/extconf.rb +0 -98
- data/ext/sunos/sunos.c +0 -374
- data/ext/sunos/sunos.h +0 -177
- data/ext/version.h +0 -2
- data/test/tc_all.rb +0 -59
- data/test/tc_freebsd.rb +0 -45
- data/test/tc_hpux.rb +0 -49
- data/test/tc_kvm_bsd.rb +0 -31
- data/test/tc_linux.rb +0 -45
- data/test/tc_sunos.rb +0 -52
- data/test/tc_top.rb +0 -26
- data/test/tc_windows.rb +0 -40
- data/test/test_memleak.rb +0 -54
@@ -0,0 +1,456 @@
|
|
1
|
+
########################################################################
|
2
|
+
# proctable.rb
|
3
|
+
#
|
4
|
+
# A pure Ruby version of sys-proctable for SunOS 5.8 or later.
|
5
|
+
########################################################################
|
6
|
+
require 'ffi'
|
7
|
+
require 'sys/proctable/version'
|
8
|
+
|
9
|
+
# The Sys module serves as a namespace only.
|
10
|
+
module Sys
|
11
|
+
|
12
|
+
# The ProcTable class encapsulates process table information.
|
13
|
+
class ProcTable
|
14
|
+
extend FFI::Library
|
15
|
+
|
16
|
+
class Error < StandardError; end
|
17
|
+
|
18
|
+
# There is no constructor
|
19
|
+
private_class_method :new
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
class Timeval < FFI::Struct
|
24
|
+
layout(:tv_sec, :time_t, :tv_usec, :time_t)
|
25
|
+
end
|
26
|
+
|
27
|
+
class LWPSInfo < FFI::Struct
|
28
|
+
layout(
|
29
|
+
:pr_flag, :int,
|
30
|
+
:pr_lwpid, :id_t,
|
31
|
+
:pr_addr, :uintptr_t,
|
32
|
+
:pr_wchan, :uintptr_t,
|
33
|
+
:pr_stype, :char,
|
34
|
+
:pr_state, :char,
|
35
|
+
:pr_sname, :char,
|
36
|
+
:pr_nice, :char,
|
37
|
+
:pr_syscall, :short,
|
38
|
+
:pr_oldpri, :char,
|
39
|
+
:pr_cpu, :char,
|
40
|
+
:pr_pri, :int,
|
41
|
+
:pr_pctcpu, :ushort_t,
|
42
|
+
:pr_pad, :ushort_t,
|
43
|
+
:pr_start, Timeval,
|
44
|
+
:pr_time, Timeval,
|
45
|
+
:pr_clname, [:char, 8],
|
46
|
+
:pr_name, [:char, 16],
|
47
|
+
:pr_onpro, :int,
|
48
|
+
:pr_bindpro, :int,
|
49
|
+
:pr_bindpset, :int,
|
50
|
+
:pr_filler, [:int, 5]
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
54
|
+
class PSInfo < FFI::Struct
|
55
|
+
layout(
|
56
|
+
:pr_flag, :int,
|
57
|
+
:pr_nlwp, :int,
|
58
|
+
:pr_pid, :pid_t,
|
59
|
+
:pr_ppid, :pid_t,
|
60
|
+
:pr_pgid, :pid_t,
|
61
|
+
:pr_sid, :pid_t,
|
62
|
+
:pr_uid, :uid_t,
|
63
|
+
:pr_euid, :uid_t,
|
64
|
+
:pr_gid, :gid_t,
|
65
|
+
:pr_egid, :gid_t,
|
66
|
+
:pr_addr, :uintptr_t,
|
67
|
+
:pr_size, :size_t,
|
68
|
+
:pr_rssize, :size_t,
|
69
|
+
:pr_pad1, :size_t,
|
70
|
+
:pr_ttydev, :dev_t,
|
71
|
+
:pr_pctcpu, :ushort_t,
|
72
|
+
:pr_pctmem, :ushort_t,
|
73
|
+
:pr_start, Timeval,
|
74
|
+
:pr_time, Timeval,
|
75
|
+
:pr_ctime, Timeval,
|
76
|
+
:pr_fname, [:char, 16],
|
77
|
+
:pr_psargs, [:char, 80],
|
78
|
+
:pr_wstat, :int,
|
79
|
+
:pr_argc, :int,
|
80
|
+
:pr_argv, :uintptr_t,
|
81
|
+
:pr_envp, :uintptr_t,
|
82
|
+
:pr_dmodel, :char,
|
83
|
+
:pr_pad2, [:char, 3],
|
84
|
+
:pr_taskid, :taskid_t,
|
85
|
+
:pr_projid, :projid_t,
|
86
|
+
:pr_nzomb, :int,
|
87
|
+
:pr_poolid, :poolid_t,
|
88
|
+
:pr_zoneid, :zoneid_t,
|
89
|
+
:pr_contract, :id_t,
|
90
|
+
:pr_filler, [:int, 1],
|
91
|
+
:pr_lwp, LWPSInfo
|
92
|
+
)
|
93
|
+
end
|
94
|
+
|
95
|
+
class PRUsage < FFI::Struct
|
96
|
+
layout(
|
97
|
+
:pr_lwpid, :id_t,
|
98
|
+
:pr_count, :int,
|
99
|
+
:pr_tstamp, Timeval,
|
100
|
+
:pr_create, Timeval,
|
101
|
+
:pr_term, Timeval,
|
102
|
+
:pr_rtime, Timeval,
|
103
|
+
:pr_utime, Timeval,
|
104
|
+
:pr_stime, Timeval,
|
105
|
+
:pr_ttime, Timeval,
|
106
|
+
:pr_tftime, Timeval,
|
107
|
+
:pr_dftime, Timeval,
|
108
|
+
:pr_kftime, Timeval,
|
109
|
+
:pr_ltime, Timeval,
|
110
|
+
:pr_slptime, Timeval,
|
111
|
+
:pr_wtime, Timeval,
|
112
|
+
:pr_stoptime, Timeval,
|
113
|
+
:pr_filetime, [Timeval,6],
|
114
|
+
:pr_minf, :ulong_t,
|
115
|
+
:pr_majf, :ulong_t,
|
116
|
+
:pr_nswap, :ulong_t,
|
117
|
+
:pr_inblk, :ulong_t,
|
118
|
+
:pr_oublk, :ulong_t,
|
119
|
+
:pr_msnd, :ulong_t,
|
120
|
+
:pr_mrcv, :ulong_t,
|
121
|
+
:pr_sigs, :ulong_t,
|
122
|
+
:pr_vctx, :ulong_t,
|
123
|
+
:pr_ictx, :ulong_t,
|
124
|
+
:pr_sysc, :ulong_t,
|
125
|
+
:pr_ioch, :ulong_t,
|
126
|
+
:filler, [:ulong_t, 10]
|
127
|
+
)
|
128
|
+
end
|
129
|
+
|
130
|
+
PRNODEV = (1<<FFI::Platform::ADDRESS_SIZE)-1
|
131
|
+
|
132
|
+
@fields = [
|
133
|
+
:flag, # process flags (deprecated)
|
134
|
+
:nlwp, # number of active lwp's in the process
|
135
|
+
:pid, # unique process id
|
136
|
+
:ppid, # process id of parent
|
137
|
+
:pgid, # pid of session leader
|
138
|
+
:sid, # session id
|
139
|
+
:uid, # real user id
|
140
|
+
:euid, # effective user id
|
141
|
+
:gid, # real group id
|
142
|
+
:egid, # effective group id
|
143
|
+
:addr, # address of the process
|
144
|
+
:size, # size of process in kbytes
|
145
|
+
:rssize, # resident set size in kbytes
|
146
|
+
:ttydev, # tty device (or PRNODEV)
|
147
|
+
:pctcpu, # % of recent cpu used by all lwp's
|
148
|
+
:pctmem, # % of system memory used by process
|
149
|
+
:start, # absolute process start time
|
150
|
+
:time, # usr + sys cpu time for this process
|
151
|
+
:ctime, # usr + sys cpu time for reaped children
|
152
|
+
:fname, # name of the exec'd file
|
153
|
+
:psargs, # initial characters argument list - same as cmdline
|
154
|
+
:wstat, # if a zombie, the wait status
|
155
|
+
:argc, # initial argument count
|
156
|
+
:argv, # address of initial argument vector
|
157
|
+
:envp, # address of initial environment vector
|
158
|
+
:dmodel, # data model of the process
|
159
|
+
:taskid, # task id
|
160
|
+
:projid, # project id
|
161
|
+
:nzomb, # number of zombie lwp's in the process
|
162
|
+
:poolid, # pool id
|
163
|
+
:zoneid, # zone id
|
164
|
+
:contract, # process contract
|
165
|
+
:lwpid, # lwp id
|
166
|
+
:wchan, # wait address for sleeping lwp
|
167
|
+
:stype, # synchronization event type
|
168
|
+
:state, # numeric lwp state
|
169
|
+
:sname, # printable character for state
|
170
|
+
:nice, # nice for cpu usage
|
171
|
+
:syscall, # system call number (if in syscall)
|
172
|
+
:pri, # priority
|
173
|
+
:clname, # scheduling class name
|
174
|
+
:name, # name of system lwp
|
175
|
+
:onpro, # processor which last ran thsi lwp
|
176
|
+
:bindpro, # processor to which lwp is bound
|
177
|
+
:bindpset, # processor set to which lwp is bound
|
178
|
+
:count, # number of contributing lwp's
|
179
|
+
:tstamp, # current time stamp
|
180
|
+
:create, # process/lwp creation time stamp
|
181
|
+
:term, # process/lwp termination time stamp
|
182
|
+
:rtime, # total lwp real (elapsed) time
|
183
|
+
:utime, # user level cpu time
|
184
|
+
:stime, # system call cpu time
|
185
|
+
:ttime, # other system trap cpu time
|
186
|
+
:tftime, # text page fault sleep time
|
187
|
+
:dftime, # text page fault sleep time
|
188
|
+
:kftime, # kernel page fault sleep time
|
189
|
+
:ltime, # user lock wait sleep time
|
190
|
+
:slptime, # all other sleep time
|
191
|
+
:wtime, # wait-cpu (latency) time
|
192
|
+
:stoptime, # stopped time
|
193
|
+
:minf, # minor page faults
|
194
|
+
:majf, # major page faults
|
195
|
+
:nswap, # swaps
|
196
|
+
:inblk, # input blocks
|
197
|
+
:oublk, # output blocks
|
198
|
+
:msnd, # messages sent
|
199
|
+
:mrcv, # messages received
|
200
|
+
:sigs, # signals received
|
201
|
+
:vctx, # voluntary context switches
|
202
|
+
:ictx, # involuntary context switches
|
203
|
+
:sysc, # system calls
|
204
|
+
:ioch, # chars read and written
|
205
|
+
:path, # array of symbolic link paths from /proc/<pid>/path
|
206
|
+
:contracts, # array symbolic link paths from /proc/<pid>/contracts
|
207
|
+
:fd, # array of used file descriptors
|
208
|
+
:cmd_args, # array of command line arguments
|
209
|
+
:environ, # hash of environment associated with the process,
|
210
|
+
:cmdline # joined cmd_args if present, otherwise psargs
|
211
|
+
]
|
212
|
+
|
213
|
+
public
|
214
|
+
|
215
|
+
ProcTableStruct = Struct.new("ProcTableStruct", *@fields) do
|
216
|
+
alias comm fname
|
217
|
+
end
|
218
|
+
|
219
|
+
# In block form, yields a ProcTableStruct for each process entry that you
|
220
|
+
# have rights to. This method returns an array of ProcTableStruct's in
|
221
|
+
# non-block form.
|
222
|
+
#
|
223
|
+
# If a +pid+ is provided, then only a single ProcTableStruct is yielded or
|
224
|
+
# returned, or nil if no process information is found for that +pid+.
|
225
|
+
#
|
226
|
+
# Example:
|
227
|
+
#
|
228
|
+
# # Iterate over all processes
|
229
|
+
# ProcTable.ps do |proc_info|
|
230
|
+
# p proc_info
|
231
|
+
# end
|
232
|
+
#
|
233
|
+
# # Print process table information for only pid 1001
|
234
|
+
# p ProcTable.ps(pid: 1001)
|
235
|
+
#
|
236
|
+
# # Skip prusage information
|
237
|
+
# p ProcTable.ps(prusage: false)
|
238
|
+
#
|
239
|
+
def self.ps(**kwargs)
|
240
|
+
pid = kwargs[:pid]
|
241
|
+
prusage_info = kwargs[:prusage]
|
242
|
+
|
243
|
+
raise TypeError unless pid.is_a?(Numeric) if pid
|
244
|
+
|
245
|
+
array = block_given? ? nil : []
|
246
|
+
struct = nil
|
247
|
+
|
248
|
+
Dir.foreach("/proc") do |file|
|
249
|
+
next if file =~ /\D/ # Skip non-numeric entries under /proc
|
250
|
+
|
251
|
+
# Only return information for a given pid, if provided
|
252
|
+
next unless file.to_i == pid if pid
|
253
|
+
|
254
|
+
# Skip over any entries we don't have permissions to read
|
255
|
+
next unless File.readable?("/proc/#{file}/psinfo")
|
256
|
+
|
257
|
+
data = IO.read("/proc/#{file}/psinfo") rescue next
|
258
|
+
psinfo = PSInfo.new(FFI::MemoryPointer.from_string(data))
|
259
|
+
|
260
|
+
struct = ProcTableStruct.new
|
261
|
+
|
262
|
+
struct.flag = psinfo[:pr_flag]
|
263
|
+
struct.nlwp = psinfo[:pr_nlwp]
|
264
|
+
struct.pid = psinfo[:pr_pid]
|
265
|
+
struct.ppid = psinfo[:pr_ppid]
|
266
|
+
struct.pgid = psinfo[:pr_pgid]
|
267
|
+
struct.sid = psinfo[:pr_sid]
|
268
|
+
struct.uid = psinfo[:pr_uid]
|
269
|
+
struct.euid = psinfo[:pr_euid]
|
270
|
+
struct.gid = psinfo[:pr_gid]
|
271
|
+
struct.egid = psinfo[:pr_egid]
|
272
|
+
struct.addr = psinfo[:pr_addr]
|
273
|
+
struct.size = psinfo[:pr_size] * 1024 # bytes
|
274
|
+
struct.rssize = psinfo[:pr_rssize] * 1024 # bytes
|
275
|
+
struct.ttydev = psinfo[:pr_ttydev] == PRNODEV ? -1 : psinfo[:pr_ttydev]
|
276
|
+
struct.pctcpu = (psinfo[:pr_pctcpu] * 100).to_f / 0x8000
|
277
|
+
struct.pctmem = (psinfo[:pr_pctmem] * 100).to_f / 0x8000
|
278
|
+
|
279
|
+
struct.start = Time.at(psinfo[:pr_start][:tv_sec])
|
280
|
+
struct.time = psinfo[:pr_time][:tv_sec]
|
281
|
+
struct.ctime = psinfo[:pr_ctime][:tv_sec]
|
282
|
+
|
283
|
+
struct.fname = psinfo[:pr_fname].to_s
|
284
|
+
struct.psargs = psinfo[:pr_psargs].to_s
|
285
|
+
struct.wstat = psinfo[:pr_wstat]
|
286
|
+
struct.argc = psinfo[:pr_argc]
|
287
|
+
struct.argv = psinfo[:pr_argv]
|
288
|
+
struct.envp = psinfo[:pr_envp]
|
289
|
+
struct.dmodel = psinfo[:pr_dmodel]
|
290
|
+
|
291
|
+
struct.taskid = psinfo[:pr_taskid]
|
292
|
+
struct.projid = psinfo[:pr_projid]
|
293
|
+
struct.nzomb = psinfo[:pr_nzomb]
|
294
|
+
struct.poolid = psinfo[:pr_poolid]
|
295
|
+
struct.zoneid = psinfo[:pr_zoneid]
|
296
|
+
struct.contract = psinfo[:pr_contract]
|
297
|
+
|
298
|
+
### LWPSINFO struct info
|
299
|
+
|
300
|
+
struct.lwpid = psinfo[:pr_lwp][:pr_lwpid]
|
301
|
+
struct.wchan = psinfo[:pr_lwp][:pr_wchan]
|
302
|
+
struct.stype = psinfo[:pr_lwp][:pr_stype]
|
303
|
+
struct.state = psinfo[:pr_lwp][:pr_state]
|
304
|
+
struct.sname = psinfo[:pr_lwp][:pr_sname].chr
|
305
|
+
struct.nice = psinfo[:pr_lwp][:pr_nice]
|
306
|
+
struct.syscall = psinfo[:pr_lwp][:pr_syscall]
|
307
|
+
struct.pri = psinfo[:pr_lwp][:pr_pri]
|
308
|
+
struct.clname = psinfo[:pr_lwp][:pr_clname].to_s
|
309
|
+
struct.name = psinfo[:pr_lwp][:pr_name].to_s
|
310
|
+
struct.onpro = psinfo[:pr_lwp][:pr_onpro]
|
311
|
+
struct.bindpro = psinfo[:pr_lwp][:pr_bindpro]
|
312
|
+
struct.bindpset = psinfo[:pr_lwp][:pr_bindpset]
|
313
|
+
|
314
|
+
# Get the full command line out of /proc/<pid>/as.
|
315
|
+
begin
|
316
|
+
File.open("/proc/#{file}/as") do |fd|
|
317
|
+
fd.sysseek(struct.argv, IO::SEEK_SET)
|
318
|
+
address = fd.sysread(struct.argc * 4).unpack("L")[0]
|
319
|
+
|
320
|
+
struct.cmd_args = []
|
321
|
+
|
322
|
+
0.upto(struct.argc - 1){ |i|
|
323
|
+
fd.sysseek(address, IO::SEEK_SET)
|
324
|
+
data = fd.sysread(128)[/^[^\0]*/] # Null strip
|
325
|
+
struct.cmd_args << data
|
326
|
+
address += data.length + 1 # Add 1 for the space
|
327
|
+
}
|
328
|
+
|
329
|
+
# Get the environment hash associated with the process.
|
330
|
+
struct.environ = {}
|
331
|
+
|
332
|
+
fd.sysseek(struct.envp, IO::SEEK_SET)
|
333
|
+
|
334
|
+
env_address = fd.sysread(128).unpack("L")[0]
|
335
|
+
|
336
|
+
# TODO: Optimization potential here.
|
337
|
+
loop do
|
338
|
+
fd.sysseek(env_address, IO::SEEK_SET)
|
339
|
+
data = fd.sysread(1024)[/^[^\0]*/] # Null strip
|
340
|
+
break if data.empty?
|
341
|
+
key, value = data.split('=')
|
342
|
+
struct.environ[key] = value
|
343
|
+
env_address += data.length + 1 # Add 1 for the space
|
344
|
+
end
|
345
|
+
end
|
346
|
+
rescue Errno::EACCES, Errno::EOVERFLOW, EOFError, RangeError
|
347
|
+
# Skip this if we don't have proper permissions, if there's
|
348
|
+
# no associated environment, or if there's a largefile issue.
|
349
|
+
rescue Errno::ENOENT
|
350
|
+
next # The process has terminated. Bail out!
|
351
|
+
end
|
352
|
+
|
353
|
+
### struct prusage
|
354
|
+
|
355
|
+
if prusage_info != false
|
356
|
+
begin
|
357
|
+
data = IO.read("/proc/#{file}/usage")
|
358
|
+
prusage = PRUsage.new(FFI::MemoryPointer.from_string(data))
|
359
|
+
|
360
|
+
struct.count = prusage[:pr_count]
|
361
|
+
struct.tstamp = prusage[:pr_tstamp][:tv_sec]
|
362
|
+
struct.create = prusage[:pr_create][:tv_sec]
|
363
|
+
struct.term = prusage[:pr_term][:tv_sec]
|
364
|
+
struct.rtime = prusage[:pr_rtime][:tv_sec]
|
365
|
+
struct.utime = prusage[:pr_utime][:tv_sec]
|
366
|
+
struct.stime = prusage[:pr_stime][:tv_sec]
|
367
|
+
struct.ttime = prusage[:pr_ttime][:tv_sec]
|
368
|
+
struct.tftime = prusage[:pr_tftime][:tv_sec]
|
369
|
+
struct.dftime = prusage[:pr_dftime][:tv_sec]
|
370
|
+
struct.kftime = prusage[:pr_kftime][:tv_sec]
|
371
|
+
struct.ltime = prusage[:pr_ltime][:tv_sec]
|
372
|
+
struct.slptime = prusage[:pr_slptime][:tv_sec]
|
373
|
+
struct.wtime = prusage[:pr_wtime][:tv_sec]
|
374
|
+
struct.stoptime = prusage[:pr_stoptime][:tv_sec]
|
375
|
+
struct.minf = prusage[:pr_minf]
|
376
|
+
struct.majf = prusage[:pr_majf]
|
377
|
+
struct.nswap = prusage[:pr_nswap]
|
378
|
+
struct.inblk = prusage[:pr_inblk]
|
379
|
+
struct.oublk = prusage[:pr_oublk]
|
380
|
+
struct.msnd = prusage[:pr_msnd]
|
381
|
+
struct.mrcv = prusage[:pr_mrcv]
|
382
|
+
struct.sigs = prusage[:pr_sigs]
|
383
|
+
struct.vctx = prusage[:pr_vctx]
|
384
|
+
struct.ictx = prusage[:pr_ictx]
|
385
|
+
struct.sysc = prusage[:pr_sysc]
|
386
|
+
struct.ioch = prusage[:pr_ioch]
|
387
|
+
rescue Errno::EACCES
|
388
|
+
# Do nothing if we lack permissions. Just move on.
|
389
|
+
rescue Errno::ENOENT
|
390
|
+
next # The process has terminated. Bail out!
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
# Information from /proc/<pid>/path. This is represented as a hash,
|
395
|
+
# with the symbolic link name as the key, and the file it links to
|
396
|
+
# as the value, or nil if it cannot be found.
|
397
|
+
#--
|
398
|
+
# Note that cwd information can be gathered from here, too.
|
399
|
+
struct.path = {}
|
400
|
+
|
401
|
+
Dir["/proc/#{file}/path/*"].each{ |entry|
|
402
|
+
link = File.readlink(entry) rescue nil
|
403
|
+
struct.path[File.basename(entry)] = link
|
404
|
+
}
|
405
|
+
|
406
|
+
# Information from /proc/<pid>/contracts. This is represented as
|
407
|
+
# a hash, with the symbolic link name as the key, and the file
|
408
|
+
# it links to as the value.
|
409
|
+
struct.contracts = {}
|
410
|
+
|
411
|
+
Dir["/proc/#{file}/contracts/*"].each{ |entry|
|
412
|
+
link = File.readlink(entry) rescue nil
|
413
|
+
struct.contracts[File.basename(entry)] = link
|
414
|
+
}
|
415
|
+
|
416
|
+
# Information from /proc/<pid>/fd. This returns an array of
|
417
|
+
# numeric file descriptors used by the process.
|
418
|
+
struct.fd = Dir["/proc/#{file}/fd/*"].map{ |f| File.basename(f).to_i }
|
419
|
+
|
420
|
+
# Use the cmd_args as the cmdline if available. Otherwise use
|
421
|
+
# the psargs. This struct member is provided to provide a measure
|
422
|
+
# of consistency with the other platform implementations.
|
423
|
+
if struct.cmd_args && struct.cmd_args.length > 0
|
424
|
+
struct.cmdline = struct.cmd_args.join(' ')
|
425
|
+
else
|
426
|
+
struct.cmdline = struct.psargs
|
427
|
+
end
|
428
|
+
|
429
|
+
# This is read-only data
|
430
|
+
struct.freeze
|
431
|
+
|
432
|
+
if block_given?
|
433
|
+
yield struct
|
434
|
+
else
|
435
|
+
array << struct
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
439
|
+
pid ? struct : array
|
440
|
+
end
|
441
|
+
|
442
|
+
# Returns an array of fields that each ProcTableStruct will contain. This
|
443
|
+
# may be useful if you want to know in advance what fields are available
|
444
|
+
# without having to perform at least one read of the /proc table.
|
445
|
+
#
|
446
|
+
# Example:
|
447
|
+
#
|
448
|
+
# Sys::ProcTable.fields.each{ |field|
|
449
|
+
# puts "Field: #{field}"
|
450
|
+
# }
|
451
|
+
#
|
452
|
+
def self.fields
|
453
|
+
@fields.map(&:to_s)
|
454
|
+
end
|
455
|
+
end
|
456
|
+
end
|