Class: SysLite::ProcTable

Inherits:
Object
  • Object
show all
Defined in:
lib/server_metrics/lib/proctable_lite.rb

Overview

The ProcTable class encapsulates process table information.

Defined Under Namespace

Classes: Error, ProcTableStruct

Constant Summary collapse

VERSION =

The version of the sys-proctable library

'0.9.3'

Class Method Summary collapse

Class Method Details

.fieldsObject

Returns an array of fields that each ProcTableStruct will contain. This may be useful if you want to know in advance what fields are available without having to perform at least one read of the /proc table.

Example:

Sys::ProcTable.fields.each{ |field|
   puts "Field: #{field}"
}


290
291
292
# File 'lib/server_metrics/lib/proctable_lite.rb', line 290

def self.fields
  @fields
end

.ps(pid = nil) ⇒ 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(1001)

–

It's possible that a process could terminate while gathering
information for that process. When that happens, this library
will simply skip to the next record. In short, this library will
either return all information for a process, or none at all.

Raises:

  • (TypeError)


122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
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
# File 'lib/server_metrics/lib/proctable_lite.rb', line 122

def self.ps(pid=nil)
  array  = block_given? ? nil : []
  struct = nil
  raise TypeError unless pid.is_a?(Fixnum) if pid

  Dir.foreach("/proc"){ |file|
    next if file =~ /\D/ # Skip non-numeric directories
    next unless file.to_i == pid if pid

    struct = ProcTableStruct.new

    # Get /proc/<pid>/cmdline information. Strip out embedded nulls.
    # begin
    #   data = IO.read("/proc/#{file}/cmdline").tr("\000", ' ').strip
    #   struct.cmdline = data
    # rescue
    #   next # Process terminated, on to the next process
    # end

    # Get /proc/<pid>/cwd information
    # struct.cwd = File.readlink("/proc/#{file}/cwd") rescue nil

    # Get /proc/<pid>/environ information. Environment information
    # is represented as a Hash, with the environment variable as the
    # key and its value as the hash value.
    struct.environ = {}

    # begin
    #           IO.read("/proc/#{file}/environ").split("\0").each{ |str|
    #             key, value = str.split('=')
    #             struct.environ[key] = value
    #           }
    #         rescue Errno::EACCES, Errno::ESRCH, Errno::ENOENT
    #           # Ignore and move on.
    #         end

    # Get /proc/<pid>/exe information
    # struct.exe = File.readlink("/proc/#{file}/exe") rescue nil

    # Get /proc/<pid>/fd information. File descriptor information
    # is represented as a Hash, with the fd as the key, and its
    # symlink as the value.
    struct.fd = {}

    # begin
    #           Dir["/proc/#{file}/fd/*"].each do |fd|
    #             struct.fd[File.basename(fd)] = File.readlink(fd) rescue nil
    #           end
    #         rescue
    #           # Ignore and move on
    #         end

    # Get /proc/<pid>/root information
    # struct.root = File.readlink("/proc/#{file}/root") rescue nil

    # Get /proc/<pid>/stat information
    stat = IO.read("/proc/#{file}/stat") rescue next

    # Deal with spaces in comm name. Courtesy of Ara Howard.
    re = %r/\([^\)]+\)/
    comm = stat[re]
    comm.tr!(' ', '-')
    stat[re] = comm

    stat = stat.split

    struct.pid         = stat[0].to_i
    # Remove parens. Note this could be overwritten in #get_comm_group_name.
    struct.comm        = stat[1].tr('()','')
    # struct.state       = stat[2]
    struct.ppid        = stat[3].to_i
    #        struct.pgrp        = stat[4].to_i
    #        struct.session     = stat[5].to_i
    #        struct.tty_nr      = stat[6].to_i
    #        struct.tpgid       = stat[7].to_i
    #        struct.flags       = stat[8].to_i
    #        struct.minflt      = stat[9].to_i
    #        struct.cminflt     = stat[10].to_i
    #        struct.majflt      = stat[11].to_i
    #        struct.cmajflt     = stat[12].to_i
    struct.utime       = stat[13].to_i
    struct.stime       = stat[14].to_i
    # struct.cutime      = stat[15].to_i
    #        struct.cstime      = stat[16].to_i
    #        struct.priority    = stat[17].to_i
    #        struct.nice        = stat[18].to_i
    # Skip 19
    # struct.itrealvalue = stat[20].to_i
    #         struct.starttime   = stat[21].to_i
    #         struct.vsize       = stat[22].to_i
    struct.rss         = stat[23].to_i
    # struct.rlim        = stat[24].to_i
    #         struct.startcode   = stat[25].to_i
    #         struct.endcode     = stat[26].to_i
    #         struct.startstack  = stat[27].to_i
    #         struct.kstkesp     = stat[28].to_i
    #         struct.kstkeip     = stat[29].to_i
    #         struct.signal      = stat[30].to_i
    #         struct.blocked     = stat[31].to_i
    #         struct.sigignore   = stat[32].to_i
    #         struct.sigcatch    = stat[33].to_i
    #         struct.wchan       = stat[34].to_i
    #         struct.nswap       = stat[35].to_i
    #         struct.cnswap      = stat[36].to_i
    #         struct.exit_signal = stat[37].to_i
    #         struct.processor   = stat[38].to_i
    #         struct.rt_priority = stat[39].to_i
    #         struct.policy      = stat[40].to_i

    # Get /proc/<pid>/status information (name, uid, euid, gid, egid)
    # IO.foreach("/proc/#{file}/status") do |line|
    #           case line
    #             when /Name:\s*?(\w+)/
    #               struct.name = $1
    #             when /Uid:\s*?(\d+)\s*?(\d+)/
    #               struct.uid  = $1.to_i
    #               struct.euid = $2.to_i
    #             when /Gid:\s*?(\d+)\s*?(\d+)/
    #               struct.gid  = $1.to_i
    #               struct.egid = $2.to_i
    #           end
    #         end

    # If cmdline is empty use comm instead
    # struct.cmdline = struct.comm if struct.cmdline.empty?

    # Manually calculate CPU and memory usage
    # struct.pctcpu = get_pctcpu(struct.utime, struct.starttime)
    # struct.pctmem = get_pctmem(struct.rss)
    
    # don't report kthreadd chidren individually - aggregate into the parent.
    if kthreadd_child?(struct.ppid)
      @kthreadd.utime += struct.utime
      @kthreadd.stime += struct.stime
      @kthreadd.rss += struct.rss
      next
    elsif !@kthreadd and %w(kthread kthreadd).include?(struct.comm)
      @kthreadd = struct
      next
    end
    
    struct.freeze # This is read-only data

    if block_given?
      yield struct
    else
      array << struct
    end
  }

  if pid
    struct
  else 
    array << @kthreadd if @kthreadd # not added when iterating.
    array
  end
end