Class: OsCtl::Lib::OsProcess

Inherits:
Object
  • Object
show all
Defined in:
lib/libosctl/os_process.rb

Overview

Interface to system processes, reading information from `/proc`

Constant Summary collapse

TICS_PER_SECOND =
Etc.sysconf(Etc::SC_CLK_TCK).to_i

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(pid) ⇒ OsProcess

Returns a new instance of OsProcess

Parameters:

  • pid (Integer)


76
77
78
79
80
81
82
83
84
85
86
# File 'lib/libosctl/os_process.rb', line 76

def initialize(pid)
  @path = File.join('/proc', pid.to_s)
  @pid = pid
  @cache = {}
  @id_maps = {}

  volatile do
    parse_stat
    parse_status
  end
end

Instance Attribute Details

#egidInteger (readonly)

Returns:

  • (Integer)


41
42
43
# File 'lib/libosctl/os_process.rb', line 41

def egid
  @egid
end

#euidInteger (readonly)

Returns:

  • (Integer)


35
36
37
# File 'lib/libosctl/os_process.rb', line 35

def euid
  @euid
end

#nameString (readonly)

Returns:

  • (String)


47
48
49
# File 'lib/libosctl/os_process.rb', line 47

def name
  @name
end

#niceInteger (readonly)

Returns:

  • (Integer)


58
59
60
# File 'lib/libosctl/os_process.rb', line 58

def nice
  @nice
end

#nspidArray (readonly)

Returns:

  • (Array)


29
30
31
# File 'lib/libosctl/os_process.rb', line 29

def nspid
  @nspid
end

#num_threadsInteger (readonly)

Returns:

  • (Integer)


61
62
63
# File 'lib/libosctl/os_process.rb', line 61

def num_threads
  @num_threads
end

#pathObject (readonly, protected)

Returns the value of attribute path



159
160
161
# File 'lib/libosctl/os_process.rb', line 159

def path
  @path
end

#pgrpInteger (readonly)

Process group ID

Returns:

  • (Integer)


26
27
28
# File 'lib/libosctl/os_process.rb', line 26

def pgrp
  @pgrp
end

#pidInteger (readonly)

Process ID

Returns:

  • (Integer)


18
19
20
# File 'lib/libosctl/os_process.rb', line 18

def pid
  @pid
end

#ppidInteger (readonly)

Parent process ID

Returns:

  • (Integer)


22
23
24
# File 'lib/libosctl/os_process.rb', line 22

def ppid
  @ppid
end

#rgidInteger (readonly)

Returns:

  • (Integer)


38
39
40
# File 'lib/libosctl/os_process.rb', line 38

def rgid
  @rgid
end

#rssInteger (readonly)

Resident set size

Returns:

  • (Integer)


55
56
57
# File 'lib/libosctl/os_process.rb', line 55

def rss
  @rss
end

#ruidInteger (readonly)

Returns:

  • (Integer)


32
33
34
# File 'lib/libosctl/os_process.rb', line 32

def ruid
  @ruid
end

#start_timeTime (readonly)

Time when the process was started

Returns:

  • (Time)


73
74
75
# File 'lib/libosctl/os_process.rb', line 73

def start_time
  @start_time
end

#stateString (readonly)

Returns:

  • (String)


44
45
46
# File 'lib/libosctl/os_process.rb', line 44

def state
  @state
end

#sys_timeInteger (readonly)

Number of seconds this process was scheduled in kernel mode

Returns:

  • (Integer)


69
70
71
# File 'lib/libosctl/os_process.rb', line 69

def sys_time
  @sys_time
end

#user_timeInteger (readonly)

Number of seconds this process was scheduled in user mode

Returns:

  • (Integer)


65
66
67
# File 'lib/libosctl/os_process.rb', line 65

def user_time
  @user_time
end

#vmsizeInteger (readonly)

Virtual memory size

Returns:

  • (Integer)


51
52
53
# File 'lib/libosctl/os_process.rb', line 51

def vmsize
  @vmsize
end

Class Method Details

.system_start_timeObject



8
9
10
11
12
13
14
# File 'lib/libosctl/os_process.rb', line 8

def self.system_start_time
  unless @system_start_time
    @system_start_time = Time.now - File.read('/proc/uptime').strip.split.first.to_i
  end

  @system_start_time
end

Instance Method Details

#cache(key) ⇒ Object (protected)



236
237
238
239
240
241
242
# File 'lib/libosctl/os_process.rb', line 236

def cache(key)
  if @cache.has_key?(key)
    @cache[key]
  else
    @cache[key] = yield
  end
end

#cmdlineString

Read /proc/<pid>/cmdline

Returns:

  • (String)


148
149
150
# File 'lib/libosctl/os_process.rb', line 148

def cmdline
  volatile { File.read(File.join(path, 'cmdline')).gsub("\0", " ").strip }
end

#ct_egidInteger?

Returns:

  • (Integer, nil)


142
143
144
# File 'lib/libosctl/os_process.rb', line 142

def ct_egid
  uns_host_to_ns('gid', egid)
end

#ct_euidInteger?

Returns:

  • (Integer, nil)


137
138
139
# File 'lib/libosctl/os_process.rb', line 137

def ct_euid
  uns_host_to_ns('uid', euid)
end

#ct_idArray?

Return container pool and id as a tuple or nil

Returns:

  • (Array, nil)


106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/libosctl/os_process.rb', line 106

def ct_id
  cache(:ct_id) do
    volatile do
      f = File.open(File.join(path, 'cgroup'), 'r')
      line = f.readline
      f.close

      _id, _subsys, path = line.split(':')

      return if /^\/osctl\/pool\.([^\/]+)/ !~ path
      pool = $1

      return if /ct\.([^\/]+)\/user\-owned\// !~ path
      ctid = $1

      [pool, ctid]
    end
  end
end

#ct_pidInteger

Return PID as seen in the container's PID namespace

Returns:

  • (Integer)


100
101
102
# File 'lib/libosctl/os_process.rb', line 100

def ct_pid
  nspid[1]
end

#ct_rgidInteger?

Returns:

  • (Integer, nil)


132
133
134
# File 'lib/libosctl/os_process.rb', line 132

def ct_rgid
  uns_host_to_ns('gid', rgid)
end

#ct_ruidInteger?

Returns:

  • (Integer, nil)


127
128
129
# File 'lib/libosctl/os_process.rb', line 127

def ct_ruid
  uns_host_to_ns('uid', ruid)
end

#flushObject

Flush cache and read fresh information from `/proc`



153
154
155
156
# File 'lib/libosctl/os_process.rb', line 153

def flush
  @cache.clear
  @id_maps.clear
end

#grandparentOsProcess

Returns:



94
95
96
# File 'lib/libosctl/os_process.rb', line 94

def grandparent
  parent.parent
end

#id_map(type) ⇒ Object (protected)



212
213
214
# File 'lib/libosctl/os_process.rb', line 212

def id_map(type)
  @id_maps[type] ||= parse_id_map(type)
end

#parentOsProcess

Returns:



89
90
91
# File 'lib/libosctl/os_process.rb', line 89

def parent
  self.class.new(ppid)
end

#parse_id_map(type) ⇒ Object (protected)



216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'lib/libosctl/os_process.rb', line 216

def parse_id_map(type)
  volatile do
    id_map = OsCtl::Lib::IdMap.new

    File.open(File.join(path, "#{type}_map"), 'r') do |f|
      f.each_line do |line|
        id_map.add_from_string(line, separator: ' ')
      end
    end

    id_map
  end
end

#parse_statObject (protected)



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/libosctl/os_process.rb', line 161

def parse_stat
  File.open(File.join(path, 'stat'), 'r') do |f|
    line = f.readline
    fields = line[line.rindex(')') + 1..-1].split

    # The third field in /proc/<pid>/stat (State) is the first in here, i.e.
    # substract 3 from field index documented in man proc to get
    # the appropriate field
    @state = fields[0]
    @ppid = fields[1].to_i
    @pgrp = fields[2].to_i
    @user_time = fields[11].to_i / TICS_PER_SECOND
    @sys_time = fields[12].to_i / TICS_PER_SECOND
    @nice = fields[16].to_i
    @num_threads = fields[17].to_i
    @start_time = self.class.system_start_time + (fields[19].to_i / TICS_PER_SECOND)
    @vmsize = fields[20].to_i
    @rss = fields[21].to_i
  end
end

#parse_statusObject (protected)



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
# File 'lib/libosctl/os_process.rb', line 182

def parse_status
  File.open(File.join(path, 'status'), 'r') do |f|
    f.each_line do |line|
      parts = line.split(':')
      next if parts.count != 2

      k = parts[0].strip
      v = parts[1].strip

      case k
      when 'NSpid'
        @nspid = v.split.map(&:to_i)

      when 'Uid'
        @ruid, @euid, @svuid, @fsuid = v.split.map(&:to_i)

      when 'Gid'
        @rgid, @egid, @svgid, @fsgid = v.split.map(&:to_i)

      when 'Name'
        @name = v
      end
    end
  end
end

#uns_host_to_ns(type, host_id) ⇒ Object (protected)



208
209
210
# File 'lib/libosctl/os_process.rb', line 208

def uns_host_to_ns(type, host_id)
  id_map(type).host_to_ns(host_id)
end

#volatileObject (protected)



230
231
232
233
234
# File 'lib/libosctl/os_process.rb', line 230

def volatile
  yield
rescue Errno::ENOENT
  raise Exceptions::OsProcessNotFound, pid
end