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)

Returns:

  • (String)

    containing matched protocol,ip and port (example: tcp:127.0.0.1:8080)



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

Parameters:

  • attrs (Hash)

    hash list contains process attributes @option proc_uptime [Integer] - process uptime @option cpu_time [Integer] total cpu time spend in kernel and user mode

Returns:

  • (Float)

    average process cpu usage from start



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()

Returns:

  • (Integer)


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

Returns:

  • (Array<ProcInfo>)
    • list current running processes



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')

Returns:

  • (Boolen)


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,'')

Parameters:

  • attrs (Hash)

    hash list contains process attributes

  • memtotal (Integer)

    total usable RAM

  • :vmrss (Hash)

    a customizable set of options

Returns:

  • (Float)


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

Returns:

  • (Integer)


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

Returns:

  • (Array<Hash>)

    list all used tcp/udp sockets



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)

Parameters:

  • pid (Fixnum)

    process pid

Returns:

  • (String)


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)

Parameters:

  • pid (Fixnum)

    process pid

Returns:

  • (aTime)


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)

Parameters:

  • pid (Fixnum)

    process pid

Returns:

  • (String)


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)

Parameters:

  • pid (Fixnum)

    process pid

Returns:

  • (String)


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

Parameters:

  • attrs (Hash)

    hash list contains process attributes

  • sockets (Array<Hash>)

    list sockets from /proc/net/tcp /proc/net/udp file



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]

Parameters:

  • attrs (Hash)

    hash list contains process attributes



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

Parameters:

  • attrs (Hash)

    hash list contains process attributes



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

Parameters:

  • pid (Fixnum)

    process pid

Returns:

  • (Array<Hash>)


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)

Parameters:

  • attrs (Hash)

    hash list contains process attributes

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)

Parameters:

  • attrs (Hash)

    hash list contains process attributes

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)

Parameters:

  • pid (Fixnum)

    process pid

Returns:

  • (String)


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()

Returns:

  • (Integer)


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