Class: HawatelPS::Linux::ProcFetch

Inherits:
Object
  • Object
show all
Defined in:
lib/hawatel_ps/linux/proc_fetch.rb

Class Method Summary collapse

Class Method Details

.compare_socket(file, sockets) ⇒ String (private)

Match socket id from /proc/<pid>/fd with /proc/net/(tcp|udp)



251
252
253
254
255
256
# File 'lib/hawatel_ps/linux/proc_fetch.rb', line 251

def compare_socket(file, sockets)
  sockets.each do |socket|
    return "#{socket[:protocol]}:#{socket[:address]}:#{socket[:port]}" if file =~ /#{socket[:id]}/
  end
  return nil
end

.cpu_percent(attrs) ⇒ Float (private)

Calculate %CPU usage per process



283
284
285
286
287
288
289
290
291
292
# File 'lib/hawatel_ps/linux/proc_fetch.rb', line 283

def cpu_percent(attrs)
  hertz = cpu_tck
  sec = uptime - attrs[:proc_uptime] / hertz
  if attrs[:cpu_time] > 0 && sec > 0
    cpu = (attrs[:cpu_time] * 1000 / hertz) / sec
    "#{cpu / 10}.#{cpu % 10}".to_f
  else
    return 0.0
  end
end

.cpu_tckInteger (private)

Return the number of clock ticks

Examples:

cpu_tck()


310
311
312
313
314
# File 'lib/hawatel_ps/linux/proc_fetch.rb', line 310

def cpu_tck
  `getconf CLK_TCK`.to_i
rescue
  return 100
end

.get_processArray<ProcInfo>

Genererate ProcInfo objects list

Examples:

get_process.each do |process|
 p process.pid
end


14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/hawatel_ps/linux/proc_fetch.rb', line 14

def get_process
  proc_table = Array.new
  memtotal   = memory_total
  sockets    = open_ports
  Dir.foreach("/proc").each do |pid|
     if is_numeric?(pid)
       attrs = Hash.new
       attrs[:pid] = pid.to_i
       attrs[:cwd] = process_cwd(pid)
       attrs[:username] = process_username(pid)
       attrs[:cmdline]  = process_cmdline(pid)
       attrs[:ctime]    = process_ctime(pid)
       attrs[:limits]   = process_limits(pid)
       attrs[:environ]  = process_env(pid)
       attrs[:childs]   = Array.new
       process_io(attrs)
       process_files(attrs, sockets)
       process_status(attrs)
       process_stat(attrs)
       attrs[:memory_percent] = memory_percent(attrs, memtotal)
       proc_table << attrs
     end
  end
  return proc_table
end

.is_numeric?(obj) ⇒ Boolen (private)

Check if object is numeric

Examples:

is_numeric?('2323')


300
301
302
# File 'lib/hawatel_ps/linux/proc_fetch.rb', line 300

def is_numeric?(obj)
  obj.to_s.match(/\A[+-]?\d+?(\.\d+)?\Z/) == nil ? false : true
end

.memory_percent(attrs, memtotal) ⇒ Float (private)

Calculate percent of memory usage by process

Examples:

memory_percent(container,'')


382
383
384
385
386
387
388
# File 'lib/hawatel_ps/linux/proc_fetch.rb', line 382

def memory_percent(attrs, memtotal)
  if attrs[:vmrss]
    return (attrs[:vmrss].to_f / memtotal.to_f * 100).round(2)
  else
    nil
  end
end

.memory_totalInteger (private)

Get total physical memory (RAM) size

Examples:

memory_total


396
397
398
399
400
# File 'lib/hawatel_ps/linux/proc_fetch.rb', line 396

def memory_total
  File.foreach('/proc/meminfo').each do |line|
    return line.split(' ')[1].to_i if line =~ /MemTotal:/
  end
end

.open_portsArray<Hash> (private)

Get list open tcp/upd ports from net/tcp and net/udp file and replace to decimal

Examples:

sockets = open_ports()
sockets.each do |socket|
   puts "#{socket[:address]} #{socket[:port]}"
end


341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
# File 'lib/hawatel_ps/linux/proc_fetch.rb', line 341

def open_ports
  socket_list  = Array.new
  ['tcp','udp'].each do |protocol|
    File.foreach("/proc/net/#{protocol}").each do |line|
      hex_port = line.split(' ')[1].split(':')[1]
      hex_ip   = line.split(' ')[1].split(':')[0].scan(/../)
      socketid = line.split(' ')[9]
      if hex_port =~ /$$$$/
        hex_ip.map! { |e| e = e.to_i(16) }
        socket_attrs = { :address => "#{hex_ip[3]}.#{hex_ip[2]}.#{hex_ip[1]}.#{hex_ip[0]}",
                         :port => hex_port.to_i(16),
                         :protocol => protocol,
                         :id => socketid }
        socket_list << socket_attrs
      end
    end
  end
  return socket_list
end

.process_cmdline(pid) ⇒ String (private)

Note:

read access to io file are restricted only to owner of process

Get command line arguments

Examples:

process_cmdline(312)


165
166
167
168
169
170
171
172
173
174
# File 'lib/hawatel_ps/linux/proc_fetch.rb', line 165

def process_cmdline(pid)
  cmdline_file = "/proc/#{pid}/cmdline"
  if File.readable? (cmdline_file)
    File.foreach(cmdline_file).each do |line|
      return line
    end
  else
    'Permission denied'
  end
end

.process_ctime(pid) ⇒ aTime (private)

Get ctime of process from pid file timestamp

Examples:

process_ctime(122)


139
140
141
142
# File 'lib/hawatel_ps/linux/proc_fetch.rb', line 139

def process_ctime(pid)
  pid_dir = "/proc/#{pid}"
  (Dir.exist?(pid_dir)) ? File.ctime(pid_dir) : 0
end

.process_cwd(pid) ⇒ String (private)

Note:

read access to cwd file are restricted only to owner of process

Get current work directory

Examples:

process_cwd(323)


152
153
154
155
# File 'lib/hawatel_ps/linux/proc_fetch.rb', line 152

def process_cwd(pid)
  cwd_file = "/proc/#{pid}/cwd"
  (File.readable?(cwd_file)) ? File.readlink(cwd_file) : 'Permission denied'
end

.process_env(pid) ⇒ String (private)

Note:

read access to fd directory are restricted only to owner of process

Get environment variables from environ file

Examples:

process_cmdline(312)


266
267
268
269
270
271
272
273
274
275
# File 'lib/hawatel_ps/linux/proc_fetch.rb', line 266

def process_env(pid)
  environ_file = "/proc/#{pid}/environ"
  if File.readable? (environ_file)
    File.foreach(environ_file).each do |line|
      return line.split("\x0")
    end
  else
    'Permission denied'
  end
end

.process_files(attrs, sockets) ⇒ Object (private)

Note:

read access to fd directory are restricted only to owner of process

Get & set open files and sockets from fd directory in attrs container



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
# File 'lib/hawatel_ps/linux/proc_fetch.rb', line 222

def process_files(attrs, sockets)
  fd_dir  = "/proc/#{attrs[:pid]}/fd"
  files   = Array.new
  ports   = Array.new
  if File.readable?(fd_dir)
    Dir.foreach(fd_dir).each do |fd|
      if is_numeric?(fd)
        file = File.readlink("#{fd_dir}/#{fd}")
        attrs[:tty] = file if fd == '0'
        if file =~ /^\// && file !~ /^\/(dev|proc)/
          files << file
        elsif file =~ /socket/
          net_listen = compare_socket(file, sockets)
          if net_listen; ports << net_listen end
        end
      end
    end
    attrs[:open_files] = files
    attrs[:listen_ports] = ports
  else
    attrs[:open_files] = 'Permission denied'
    attrs[:listen_ports] = 'Permission denied'
    attrs[:tty] = 'Permission denied'
  end
end

.process_io(attrs) ⇒ Object (private)

Note:

read access to io file are restricted only to owner of process

Read I/O attributes from /proc/<pid>/io file and save in attrs container

Examples:

attrs = Hash.new
process_io(Hash)
p attrs[:wchar]


91
92
93
94
95
96
97
98
99
100
# File 'lib/hawatel_ps/linux/proc_fetch.rb', line 91

def process_io(attrs)
  process_io_set_nil(attrs)
  io_file = "/proc/#{attrs[:pid]}/io"
  if File.readable?(io_file)
    File.foreach(io_file).each do |attr|
      name = attr.split(' ')[0].chop
      attrs[:"#{name}"] = attr.split(' ')[1].to_i
    end
  end
end

.process_io_set_nil(attrs) ⇒ Object (private)

Set default value for i/o attributes in attrs container



105
106
107
108
109
# File 'lib/hawatel_ps/linux/proc_fetch.rb', line 105

def process_io_set_nil(attrs)
  ['rchar','wchar','syscr','syscw','read_bytes','write_bytes','cancelled_write_bytes'].each do |attr|
    attrs[:"#{attr}"] = 'Permission denied'
  end
end

.process_limits(pid) ⇒ Array<Hash> (private)

Get soft and hard limits for process from limits file

Examples:

p = process_limits('312')

p.limits.each do |limit|
  puts "#{limit[name]} #{limit[:soft]} #{limit[:hard]}"
end


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
# File 'lib/hawatel_ps/linux/proc_fetch.rb', line 187

def process_limits(pid)
  limits_file = "/proc/#{pid}/limits"
  limits_list = Array.new
  if File.readable?(limits_file)
    File.foreach(limits_file).each do |line|
      next if (line =~ /Limit/)
      line_split = line.split(' ')
      if line.split(' ')[1] == 'processes'
        lname = "#{line_split[1]}"
        lsoft = "#{line_split[2]} #{line_split[4]}"
        lhard = "#{line_split[3]} #{line_split[4]}"
      else
        lname = "#{line_split[1]}_#{line_split[2]}"
        if line.split(' ')[5]
          lsoft = "#{line_split[3]} #{line_split[5]}"
          lhard = "#{line_split[4]} #{line_split[5]}"
        else
          lsoft = "#{line_split[3]}"
          lhard = "#{line_split[4]}"
        end
      end
      limits_attrs = { :name => "#{lname}", :soft => "#{lsoft}", :hard => "#{lhard}" }
      limits_list << limits_attrs
    end
  else
    limits_list = ['Permission denied']
  end
  limits_list
end

.process_stat(attrs) ⇒ Object (private)

Read statistics from /proc/<pid>/stat file and save in attrs container

Examples:

container = Hash.new
process_stat(container)

See Also:



119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/hawatel_ps/linux/proc_fetch.rb', line 119

def process_stat(attrs)
  stat_file = "/proc/#{attrs[:pid]}/stat"
  if File.readable?  (stat_file)
    File.foreach(stat_file).each do |line|
      attr = line.split(' ')
      attrs[:utime] = attr[13].to_i
      attrs[:stime] = attr[14].to_i
      attrs[:cpu_time] = (attrs[:utime] +  attrs[:stime])
      attrs[:cpu_percent] = cpu_percent({:cpu_time => attrs[:cpu_time], :proc_uptime => attr[21].to_i })
    end
  end
end

.process_status(attrs) ⇒ Object (private)

Get process attributes from /proc/<pid>/status file and save in Hash container

Examples:

process_status(Hash)

See Also:



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/hawatel_ps/linux/proc_fetch.rb', line 47

def process_status(attrs)
  status_file = "/proc/#{attrs[:pid]}/status"
  File.foreach(status_file).each do |attr|
    if attr =~ /Name:/
      attrs[:name] = attr.split(' ')[1]
    elsif attr =~ /PPid:/
      attrs[:ppid] = attr.split(' ')[1].to_i
    elsif attr =~ /State:/
      attrs[:state] = attr.split(' ')[2].to_s.chop[1..-1]
    elsif attr =~ /Uid:/
      attrs[:ruid] = attr.split(' ')[1].to_i
      attrs[:euid] = attr.split(' ')[2].to_i
      attrs[:suid] = attr.split(' ')[3].to_i
      attrs[:fsuid] = attr.split(' ')[4].to_i
    elsif attr =~ /Gid:/
      attrs[:gid] = attr.split(' ')[1].to_i
      attrs[:egid] = attr.split(' ')[2].to_i
      attrs[:sgid] = attr.split(' ')[3].to_i
      attrs[:fsgid] = attr.split(' ')[4].to_i
    elsif attr =~ /Threads:/
      attrs[:threads] = attr.split(' ')[1].to_i
    elsif attr =~ /VmSize:/
      attrs[:vmsize] = attr.split(' ')[1].to_i
    elsif attr =~ /VmRSS:/
      attrs[:vmrss] = attr.split(' ')[1].to_i
    elsif attr =~ /VmData:/
      attrs[:vmdata] = attr.split(' ')[1].to_i
    elsif attr =~ /VmSwap:/
      attrs[:vmswap] = attr.split(' ')[1].to_i
    elsif attr =~ /VmLib:/
      attrs[:vmlib] = attr.split(' ')[1].to_i
    end
  end
end

.process_username(pid) ⇒ String (private)

Get process uid and return username from passwd file

Examples:

process_username(132)


323
324
325
326
327
328
329
330
# File 'lib/hawatel_ps/linux/proc_fetch.rb', line 323

def process_username(pid)
  uid = File.stat("/proc/#{pid}").uid
  File.foreach('/etc/passwd').each do |line|
    if line.split(':')[2] == "#{uid}"
      return line.split(':')[0]
    end
  end
end

.uptimeInteger (private)

Return system uptime in second

Examples:

uptime()


367
368
369
370
371
# File 'lib/hawatel_ps/linux/proc_fetch.rb', line 367

def uptime
  File.foreach('/proc/uptime').each do |line|
    return line.split[0].to_i
  end
end