Class: OsCtl::Lib::OsProcess
- Inherits:
-
Object
- Object
- OsCtl::Lib::OsProcess
- Defined in:
- lib/libosctl/os_process.rb
Overview
Interface to system processes, reading information from `/proc`
Constant Summary collapse
Instance Attribute Summary collapse
- #egid ⇒ Integer readonly
- #euid ⇒ Integer readonly
- #name ⇒ String readonly
- #nice ⇒ Integer readonly
- #nspid ⇒ Array readonly
- #num_threads ⇒ Integer readonly
-
#opts ⇒ Object
readonly
protected
Returns the value of attribute opts.
-
#path ⇒ Object
readonly
protected
Returns the value of attribute path.
-
#pgrp ⇒ Integer
readonly
Process group ID.
-
#pid ⇒ Integer
readonly
Process ID.
-
#ppid ⇒ Integer
readonly
Parent process ID.
- #rgid ⇒ Integer readonly
-
#rss ⇒ Integer
readonly
Resident set size in bytes.
- #ruid ⇒ Integer readonly
-
#start_time ⇒ Time
readonly
Time when the process was started.
- #state ⇒ String readonly
-
#sys_time ⇒ Integer
readonly
Number of seconds this process was scheduled in kernel mode.
-
#user_time ⇒ Integer
readonly
Number of seconds this process was scheduled in user mode.
-
#vmsize ⇒ Integer
readonly
Virtual memory size in bytes.
Class Method Summary collapse
Instance Method Summary collapse
- #cache(key) ⇒ Object protected
-
#cmdline ⇒ String
Read /proc/<pid>/cmdline.
- #ct_egid ⇒ Integer?
- #ct_euid ⇒ Integer?
-
#ct_id ⇒ Array?
Return container pool and id as a tuple or nil.
-
#ct_pid ⇒ Integer
Return PID as seen in the container's PID namespace.
- #ct_rgid ⇒ Integer?
- #ct_ruid ⇒ Integer?
-
#flush ⇒ Object
Flush cache and read fresh information from `/proc`.
- #grandparent ⇒ OsProcess
- #id_map(type) ⇒ Object protected
-
#initialize(pid, **opts) ⇒ OsProcess
constructor
A new instance of OsProcess.
- #parent ⇒ OsProcess
-
#parse ⇒ Object
Menually invoke parsing of `/proc/<pid>/stat` and `/proc/<pid>/status`.
- #parse_id_map(type) ⇒ Object protected
- #parse_stat ⇒ Object protected
- #parse_status ⇒ Object protected
- #uns_host_to_ns(type, host_id) ⇒ Object protected
- #volatile ⇒ Object protected
Constructor Details
#initialize(pid, **opts) ⇒ OsProcess
Returns a new instance of OsProcess.
80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/libosctl/os_process.rb', line 80 def initialize(pid, **opts) @path = File.join('/proc', pid.to_s) @pid = pid @cache = {} @id_maps = {} @opts = opts volatile do parse_stat if opts.fetch(:parse_stat, true) parse_status if opts.fetch(:parse_status, true) end end |
Instance Attribute Details
#egid ⇒ Integer (readonly)
42 43 44 |
# File 'lib/libosctl/os_process.rb', line 42 def egid @egid end |
#euid ⇒ Integer (readonly)
36 37 38 |
# File 'lib/libosctl/os_process.rb', line 36 def euid @euid end |
#name ⇒ String (readonly)
48 49 50 |
# File 'lib/libosctl/os_process.rb', line 48 def name @name end |
#nice ⇒ Integer (readonly)
59 60 61 |
# File 'lib/libosctl/os_process.rb', line 59 def nice @nice end |
#nspid ⇒ Array (readonly)
30 31 32 |
# File 'lib/libosctl/os_process.rb', line 30 def nspid @nspid end |
#num_threads ⇒ Integer (readonly)
62 63 64 |
# File 'lib/libosctl/os_process.rb', line 62 def num_threads @num_threads end |
#opts ⇒ Object (readonly, protected)
Returns the value of attribute opts.
188 189 190 |
# File 'lib/libosctl/os_process.rb', line 188 def opts @opts end |
#path ⇒ Object (readonly, protected)
Returns the value of attribute path.
188 189 190 |
# File 'lib/libosctl/os_process.rb', line 188 def path @path end |
#pgrp ⇒ Integer (readonly)
Process group ID
27 28 29 |
# File 'lib/libosctl/os_process.rb', line 27 def pgrp @pgrp end |
#pid ⇒ Integer (readonly)
Process ID
19 20 21 |
# File 'lib/libosctl/os_process.rb', line 19 def pid @pid end |
#ppid ⇒ Integer (readonly)
Parent process ID
23 24 25 |
# File 'lib/libosctl/os_process.rb', line 23 def ppid @ppid end |
#rgid ⇒ Integer (readonly)
39 40 41 |
# File 'lib/libosctl/os_process.rb', line 39 def rgid @rgid end |
#rss ⇒ Integer (readonly)
Resident set size in bytes
56 57 58 |
# File 'lib/libosctl/os_process.rb', line 56 def rss @rss end |
#ruid ⇒ Integer (readonly)
33 34 35 |
# File 'lib/libosctl/os_process.rb', line 33 def ruid @ruid end |
#start_time ⇒ Time (readonly)
Time when the process was started
74 75 76 |
# File 'lib/libosctl/os_process.rb', line 74 def start_time @start_time end |
#state ⇒ String (readonly)
45 46 47 |
# File 'lib/libosctl/os_process.rb', line 45 def state @state end |
#sys_time ⇒ Integer (readonly)
Number of seconds this process was scheduled in kernel mode
70 71 72 |
# File 'lib/libosctl/os_process.rb', line 70 def sys_time @sys_time end |
#user_time ⇒ Integer (readonly)
Number of seconds this process was scheduled in user mode
66 67 68 |
# File 'lib/libosctl/os_process.rb', line 66 def user_time @user_time end |
#vmsize ⇒ Integer (readonly)
Virtual memory size in bytes
52 53 54 |
# File 'lib/libosctl/os_process.rb', line 52 def vmsize @vmsize end |
Class Method Details
.system_start_time ⇒ Object
9 10 11 12 13 14 15 |
# File 'lib/libosctl/os_process.rb', line 9 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)
265 266 267 268 269 270 271 |
# File 'lib/libosctl/os_process.rb', line 265 def cache(key) if @cache.has_key?(key) @cache[key] else @cache[key] = yield end end |
#cmdline ⇒ String
Read /proc/<pid>/cmdline
175 176 177 178 179 |
# File 'lib/libosctl/os_process.rb', line 175 def cmdline cache(:cmdline) do volatile { File.read(File.join(path, 'cmdline')).gsub("\0", " ").strip } end end |
#ct_egid ⇒ Integer?
169 170 171 |
# File 'lib/libosctl/os_process.rb', line 169 def ct_egid uns_host_to_ns('gid', egid) end |
#ct_euid ⇒ Integer?
164 165 166 |
# File 'lib/libosctl/os_process.rb', line 164 def ct_euid uns_host_to_ns('uid', euid) end |
#ct_id ⇒ Array?
Return container pool and id as a tuple or nil
119 120 121 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 |
# File 'lib/libosctl/os_process.rb', line 119 def ct_id cache(:ct_id) do volatile do File.open(File.join(path, 'cgroup'), 'r') do |f| # It's not enough to check the first cgroup, it can happen that # the process remains only in some cgroups that belong to # the container, e.g. on an incorrect shutdown. f.each_line do |line| begin _id, _subsys, path = line.split(':') rescue ArgumentError # We have a kernel bug in 5.10.147.7, which malforms # /proc/<pid>/cgroup contents, raising: # # invalid byte sequence in US-ASCII (ArgumentError) # break end next if /^\/osctl\/pool\.([^\/]+)/ !~ path pool = $1 next if /ct\.([^\/]+)\/user\-owned(\/|$)/ !~ path ctid = $1 return [pool, ctid] end end nil end end end |
#ct_pid ⇒ Integer
Return PID as seen in the container's PID namespace
113 114 115 |
# File 'lib/libosctl/os_process.rb', line 113 def ct_pid nspid[1] end |
#ct_rgid ⇒ Integer?
159 160 161 |
# File 'lib/libosctl/os_process.rb', line 159 def ct_rgid uns_host_to_ns('gid', rgid) end |
#ct_ruid ⇒ Integer?
154 155 156 |
# File 'lib/libosctl/os_process.rb', line 154 def ct_ruid uns_host_to_ns('uid', ruid) end |
#flush ⇒ Object
Flush cache and read fresh information from `/proc`
182 183 184 185 |
# File 'lib/libosctl/os_process.rb', line 182 def flush @cache.clear @id_maps.clear end |
#grandparent ⇒ OsProcess
107 108 109 |
# File 'lib/libosctl/os_process.rb', line 107 def grandparent parent.parent end |
#id_map(type) ⇒ Object (protected)
241 242 243 |
# File 'lib/libosctl/os_process.rb', line 241 def id_map(type) @id_maps[type] ||= parse_id_map(type) end |
#parent ⇒ OsProcess
102 103 104 |
# File 'lib/libosctl/os_process.rb', line 102 def parent self.class.new(ppid, **opts) end |
#parse ⇒ Object
Menually invoke parsing of `/proc/<pid>/stat` and `/proc/<pid>/status`
94 95 96 97 98 99 |
# File 'lib/libosctl/os_process.rb', line 94 def parse volatile do parse_stat parse_status end end |
#parse_id_map(type) ⇒ Object (protected)
245 246 247 248 249 250 251 252 253 254 255 256 257 |
# File 'lib/libosctl/os_process.rb', line 245 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_stat ⇒ Object (protected)
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
# File 'lib/libosctl/os_process.rb', line 190 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 * PAGE_SIZE end end |
#parse_status ⇒ Object (protected)
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 |
# File 'lib/libosctl/os_process.rb', line 211 def parse_status File.open(File.join(path, 'status'), 'r') do |f| f.each_line do |line| colon = line.index(':') next if colon.nil? k = line[0..(colon-1)].strip v = line[(colon+1)..-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)
237 238 239 |
# File 'lib/libosctl/os_process.rb', line 237 def uns_host_to_ns(type, host_id) id_map(type).host_to_ns(host_id) end |
#volatile ⇒ Object (protected)
259 260 261 262 263 |
# File 'lib/libosctl/os_process.rb', line 259 def volatile yield rescue Errno::ENOENT, Errno::ESRCH raise Exceptions::OsProcessNotFound, pid end |