Class: Sys::ProcTable
- Inherits:
-
Object
- Object
- Sys::ProcTable
- Extended by:
- FFI::Library, ProcTableFunctions
- Includes:
- ProcTableConstants, ProcTableStructs
- Defined in:
- lib/aix/sys/proctable.rb,
lib/linux/sys/proctable.rb,
lib/sunos/sys/proctable.rb,
lib/darwin/sys/proctable.rb,
lib/sys/proctable/version.rb,
lib/windows/sys/proctable.rb,
lib/linux/sys/proctable/smaps.rb,
lib/bsd/sys/freebsd/sys/proctable.rb,
lib/bsd/sys/dragonfly/sys/proctable.rb,
lib/linux/sys/proctable/cgroup_entry.rb
Overview
The ProcTable class encapsulates process table information
Defined Under Namespace
Classes: CgroupEntry, Error, KInfoProc, LWPSInfo, PRUsage, PSInfo, Pargs, Priority, ProcTableMapStruct, Rusage, Smaps, Timeval
Constant Summary collapse
- VERSION =
The version of the sys-proctable library
'1.3.0'.freeze
- PROC_STRUCT_FIELD_MAP =
all_members.map do |member| temp = member.to_s.split('_') sproperty = temp.size > 1 ? temp[1..-1].join('_') : temp.first [member, sproperty.to_sym] end.to_h
Constants included from ProcTableConstants
Sys::ProcTableConstants::KERN_PROC_ALL, Sys::ProcTableConstants::MAXLOGNAME, Sys::ProcTableConstants::NGROUPS
Class Attribute Summary collapse
-
.fields ⇒ Object
readonly
Returns an array of fields that each ProcTableStruct will contain.
Class Method Summary collapse
-
.ps(**kwargs) ⇒ Object
In block form, yields a ProcTableStruct for each process entry that you have rights to.
Class Attribute Details
.fields ⇒ Object (readonly)
454 455 456 |
# File 'lib/aix/sys/proctable.rb', line 454 def self.fields @fields.map{ |f| f.to_s } end |
Class Method Details
.ps(**kwargs) ⇒ Object
In block form, yields a ProcTableStruct for each process entry that you have rights to. This method returns an array of ProcTableStruct’s in non-block form.
If a pid
is provided, then only a single ProcTableStruct is yielded or returned, or nil if no process information is found for that pid
.
Example:
# Iterate over all processes
ProcTable.ps do |proc_info|
p proc_info
end
# Print process table information for only pid 1001
p ProcTable.ps(pid: 1001)
# Same as above, but do not include thread information
p ProcTable.ps(pid: 1001, thread_info: false)
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 |
# File 'lib/aix/sys/proctable.rb', line 207 def self.ps(**kwargs) pid = kwargs[:pid] raise TypeError unless pid.is_a?(Numeric) if pid array = block_given? ? nil : [] struct = nil Dir.foreach("/proc") do |file| next if file =~ /\D/ # Skip non-numeric entries under /proc # Only return information for a given pid, if provided if pid next unless file.to_i == pid end # Skip over any entries we don't have permissions to read next unless File.readable?("/proc/#{file}/psinfo") psinfo = IO.read("/proc/#{file}/psinfo") rescue next psinfo_array = psinfo.unpack(@psinfo_pack_directive) struct = ProcTableStruct.new struct.flag = psinfo_array[0] # pr_flag struct.flag2 = psinfo_array[1] # pr_flag2 struct.nlwp = psinfo_array[2] # pr_nlwp # pr__pad1 struct.uid = psinfo_array[4] # pr_uid struct.euid = psinfo_array[5] # pr_euid struct.gid = psinfo_array[6] # pr_gid struct.egid = psinfo_array[7] # pr_egid struct.pid = psinfo_array[8] # pr_pid struct.ppid = psinfo_array[9] # pr_ppid struct.pgid = psinfo_array[10] # pr_pgid struct.sid = psinfo_array[11] # pr_sid struct.ttydev = psinfo_array[12] # pr_ttydev # convert from 64-bit dev_t to 32-bit dev_t and then map the device # number to a name ttydev = struct.ttydev ttydev = (((ttydev & 0x0000FFFF00000000) >> 16) | (ttydev & 0xFFFF)) struct.s_ttydev = @devs.has_key?(ttydev) ? @devs[ttydev] : '-' struct.addr = psinfo_array[13] # pr_addr struct.size = psinfo_array[14] * 1024 # pr_size struct.rssize = psinfo_array[15] * 1024 # pr_rssize struct.start = Time.at(psinfo_array[16], psinfo_array[17]) # pr_start # skip pr_start.__pad struct.time = psinfo_array[19] # pr_time # skip pr_time.tv_nsec and pr_time.__pad struct.cid = psinfo_array[22] # pr_cid # skip pr__pad2 struct.argc = psinfo_array[24] # pr_argc struct.argv = psinfo_array[25] # pr_argv struct.envp = psinfo_array[26] # pr_envp struct.fname = psinfo_array[27] # pr_fname struct.psargs = psinfo_array[28] # pr_psargs # skip pr__pad ### lwpsinfo_t info struct.lwpid = psinfo_array[37] # pr_lwpid # skip pr_addr struct.wchan = psinfo_array[39] # pr_wchan # skip pr_flag struct.wtype = psinfo_array[41] # pr_wtype struct.state = psinfo_array[42] # pr_state struct.sname = psinfo_array[43] # pr_sname struct.nice = psinfo_array[44] # pr_nice struct.pri = psinfo_array[45] # pr_pri struct.policy = psinfo_array[46] # pr_policy struct.clname = psinfo_array[47] # pr_clname struct.onpro = psinfo_array[48] # pr_onpro struct.bindpro = psinfo_array[49] # pr_bindpro struct.ptid = psinfo_array[50] # pr_ptid # skip pr__pad1 # skip pr__pad # Get the full command line out of /proc/<pid>/as. begin File.open("/proc/#{file}/as", 'rb') do |fd| np = fd.sysseek(struct.argv, IO::SEEK_SET) if np != struct.argv raise Error, "argv seek to #{struct.argv}, result #{np}", caller end argv = fd.sysread(4).unpack('L')[0] np = fd.sysseek(argv, IO::SEEK_SET) if np != argv raise Error, "*argv seek to #{argv}, result #{np}", caller end argv = fd.sysread(4 * struct.argc).unpack("L#{struct.argc}") struct.cmd_args = [] argv.each_with_index do |address, i| np = fd.sysseek(address, IO::SEEK_SET) if np != address raise Error, "argv[#{i}] seek to #{address}, result #{np}", caller end data = fd.sysread(512)[/^[^\0]*/] # Null strip struct.cmd_args << data end # Get the environment hash associated with the process. struct.environ = {} # First have to go to the address given by struct.envp. That will # give us the address of the environment pointer array. np = fd.sysseek(struct.envp, IO::SEEK_SET) if np != struct.envp raise Error, "envp seek to #{struct.envp}, result #{np}", caller end envloc = fd.sysread(4).unpack('L')[0] n = 0 loop do np = fd.sysseek(envloc, IO::SEEK_SET) if np != envloc raise Error, "envp[#{n}] seek to #{envloc}, result #{np}", caller end envp = fd.sysread(4).unpack("L")[0] break if envp.zero? np = fd.sysseek(envp, IO::SEEK_SET) data = fd.sysread(1024)[/^[^\0]*/] # Null strip key, value = data.split('=') struct.environ[key] = value envloc += 4 n += 1 end end rescue Errno::EACCES, Errno::EOVERFLOW, EOFError # Skip this if we don't have proper permissions, if there's # no associated environment, or if there's a largefile issue. rescue Errno::ENOENT next # The process has terminated. Bail out! end # Information from /proc/<pid>/fd. This returns an array of # numeric file descriptors used by the process. struct.fd = Dir["/proc/#{file}/fd/*"].map { |f| File.basename(f).to_i } # Use the cmd_args as the cmdline if available. Otherwise use # the psargs. This struct member is provided to provide a measure # of consistency with the other platform implementations. if struct.cmd_args.nil? || struct.cmd_args.empty? struct.cmdline = struct.psargs else struct.cmdline = struct.cmd_args.join(' ') end # get current working directory from /proc/<pid>/cwd struct.cwd = File.readlink("/proc/#{file}/cwd") rescue nil # get virtual address map from /proc/<pid>/map begin struct.map = [] File.open("/proc/#{file}/map", 'rb') do |fd| loop do prmap_array = fd.sysread(176).unpack(@prmap_pack_directive) break if prmap_array[0].zero? map_struct = ProcTableMapStruct.new map_struct.size = prmap_array[0] # pr_size map_struct.vaddr = prmap_array[1] # pr_vaddr map_struct.mapname = prmap_array[2] # pr_mapname map_struct.off = prmap_array[3] # pr_off map_struct.mflags = prmap_array[4] # pr_mflags # convert pr_mflags value to string sort of like procmap outputs mflags = map_struct.mflags map_struct.s_mflags = '' sep = '' PR_MFLAGS.each do |flag| if (mflags & flag[0]).nonzero? map_struct.s_mflags << sep << flag[1] sep = '/' mflags &= ~flag[0] end end if mflags.nonzero? map_struct.s_mflags << sep << sprintf('%08x', mflags) end map_struct.pathoff = prmap_array[5] # pr_pathoff map_struct.alias = prmap_array[6] # pr_alias map_struct.gp = prmap_array[7] # pr_gp struct.map << map_struct end struct.map.each do |m| next if m.pathoff.zero? fd.sysseek(m.pathoff, IO::SEEK_SET) buf = fd.sysread(4096) buf =~ /^([^\0]*)\0([^\0]*)\0/ m.path = $2.empty? ? $1 : "#{$1}(#{$2})" end end struct.map = nil if struct.map.empty? rescue struct.map = nil end # This is read-only data struct.freeze if block_given? yield struct else array << struct end end pid ? struct : array end |