hawatel_ps 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +4 -0
  5. data/.yardopts +1 -0
  6. data/CONTRIBUTING.md +74 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +184 -0
  10. data/Rakefile +12 -0
  11. data/hawatel_ps.gemspec +29 -0
  12. data/lib/hawatel_ps/linux/proc_control.rb +75 -0
  13. data/lib/hawatel_ps/linux/proc_fetch.rb +405 -0
  14. data/lib/hawatel_ps/linux/proc_info.rb +53 -0
  15. data/lib/hawatel_ps/linux/proc_table.rb +124 -0
  16. data/lib/hawatel_ps/linux.rb +4 -0
  17. data/lib/hawatel_ps/shared/hawatelps_exception.rb +21 -0
  18. data/lib/hawatel_ps/version.rb +3 -0
  19. data/lib/hawatel_ps/windows/proc_control.rb +67 -0
  20. data/lib/hawatel_ps/windows/proc_fetch.rb +217 -0
  21. data/lib/hawatel_ps/windows/proc_info.rb +51 -0
  22. data/lib/hawatel_ps/windows/proc_table.rb +138 -0
  23. data/lib/hawatel_ps/windows/wmi/wmi_cli.rb +65 -0
  24. data/lib/hawatel_ps/windows/wmi/wmi_exception.rb +23 -0
  25. data/lib/hawatel_ps/windows/wmi/wmi_instance.rb +56 -0
  26. data/lib/hawatel_ps/windows.rb +5 -0
  27. data/lib/hawatel_ps.rb +34 -0
  28. data/spec/hawatel_ps_spec.rb +11 -0
  29. data/spec/linux/bdd/proc_spec.rb +54 -0
  30. data/spec/linux/factories/etc/passwd +32 -0
  31. data/spec/linux/factories/proc/1761/cmdline +0 -0
  32. data/spec/linux/factories/proc/1761/environ +0 -0
  33. data/spec/linux/factories/proc/1761/io +7 -0
  34. data/spec/linux/factories/proc/1761/limits +17 -0
  35. data/spec/linux/factories/proc/1761/stat +1 -0
  36. data/spec/linux/factories/proc/1761/status +46 -0
  37. data/spec/linux/factories/proc/meminfo +45 -0
  38. data/spec/linux/factories/proc/net/tcp +7 -0
  39. data/spec/linux/factories/proc/net/udp +8 -0
  40. data/spec/linux/factories/proc/uptime +1 -0
  41. data/spec/linux/support/stub_dir.rb +33 -0
  42. data/spec/linux/support/stub_file.rb +107 -0
  43. data/spec/linux/tdd/proc_fetch_spec.rb +107 -0
  44. data/spec/linux/tdd/proc_table_spec.rb +85 -0
  45. data/spec/shared/hawatelps_exception_spec.rb +13 -0
  46. data/spec/spec_helper.rb +16 -0
  47. data/spec/windows/bdd/proc_spec.rb +119 -0
  48. data/spec/windows/factories/proc_fetch_factorie.rb +76 -0
  49. data/spec/windows/tdd/proc_control_spec.rb +36 -0
  50. data/spec/windows/tdd/proc_fetch_spec.rb +73 -0
  51. data/spec/windows/tdd/proc_table_spec.rb +71 -0
  52. data/spec/windows/tdd/wmi_spec.rb +59 -0
  53. metadata +181 -0
@@ -0,0 +1,405 @@
1
+ module HawatelPS
2
+ module Linux
3
+ class ProcFetch
4
+ class << self
5
+
6
+ # Genererate ProcInfo objects list
7
+ #
8
+ # @example
9
+ # get_process.each do |process|
10
+ # p process.pid
11
+ # end
12
+ #
13
+ # @return [Array<ProcInfo>] - list current running processes
14
+ def get_process
15
+ proc_table = Array.new
16
+ memtotal = memory_total
17
+ sockets = open_ports
18
+ Dir.foreach("/proc").each do |pid|
19
+ if is_numeric?(pid)
20
+ attrs = Hash.new
21
+ attrs[:pid] = pid.to_i
22
+ attrs[:cwd] = process_cwd(pid)
23
+ attrs[:username] = process_username(pid)
24
+ attrs[:cmdline] = process_cmdline(pid)
25
+ attrs[:ctime] = process_ctime(pid)
26
+ attrs[:limits] = process_limits(pid)
27
+ attrs[:environ] = process_env(pid)
28
+ attrs[:childs] = Array.new
29
+ process_io(attrs)
30
+ process_files(attrs, sockets)
31
+ process_status(attrs)
32
+ process_stat(attrs)
33
+ attrs[:memory_percent] = memory_percent(attrs, memtotal)
34
+ proc_table << attrs
35
+ end
36
+ end
37
+ return proc_table
38
+ end
39
+
40
+ private
41
+ # @see https://www.kernel.org/doc/Documentation/filesystems/proc.txt Table 1-2
42
+ # Get process attributes from /proc/<pid>/status file and save in Hash container
43
+ #
44
+ # @example
45
+ # process_status(Hash)
46
+ # @param attrs [Hash] hash list contains process attributes
47
+ def process_status(attrs)
48
+ status_file = "/proc/#{attrs[:pid]}/status"
49
+ File.foreach(status_file).each do |attr|
50
+ if attr =~ /Name:/
51
+ attrs[:name] = attr.split(' ')[1]
52
+ elsif attr =~ /PPid:/
53
+ attrs[:ppid] = attr.split(' ')[1].to_i
54
+ elsif attr =~ /State:/
55
+ attrs[:state] = attr.split(' ')[2].to_s.chop[1..-1]
56
+ elsif attr =~ /Uid:/
57
+ attrs[:ruid] = attr.split(' ')[1].to_i
58
+ attrs[:euid] = attr.split(' ')[2].to_i
59
+ attrs[:suid] = attr.split(' ')[3].to_i
60
+ attrs[:fsuid] = attr.split(' ')[4].to_i
61
+ elsif attr =~ /Gid:/
62
+ attrs[:gid] = attr.split(' ')[1].to_i
63
+ attrs[:egid] = attr.split(' ')[2].to_i
64
+ attrs[:sgid] = attr.split(' ')[3].to_i
65
+ attrs[:fsgid] = attr.split(' ')[4].to_i
66
+ elsif attr =~ /Threads:/
67
+ attrs[:threads] = attr.split(' ')[1].to_i
68
+ elsif attr =~ /VmSize:/
69
+ attrs[:vmsize] = attr.split(' ')[1].to_i
70
+ elsif attr =~ /VmRSS:/
71
+ attrs[:vmrss] = attr.split(' ')[1].to_i
72
+ elsif attr =~ /VmData:/
73
+ attrs[:vmdata] = attr.split(' ')[1].to_i
74
+ elsif attr =~ /VmSwap:/
75
+ attrs[:vmswap] = attr.split(' ')[1].to_i
76
+ elsif attr =~ /VmLib:/
77
+ attrs[:vmlib] = attr.split(' ')[1].to_i
78
+ end
79
+ end
80
+ end
81
+
82
+ # @note read access to io file are restricted only to owner of process
83
+ # Read I/O attributes from /proc/<pid>/io file and save in attrs container
84
+ #
85
+ # @example
86
+ # attrs = Hash.new
87
+ # process_io(Hash)
88
+ # p attrs[:wchar]
89
+ #
90
+ # @param attrs [Hash] hash list contains process attributes
91
+ def process_io(attrs)
92
+ process_io_set_nil(attrs)
93
+ io_file = "/proc/#{attrs[:pid]}/io"
94
+ if File.readable?(io_file)
95
+ File.foreach(io_file).each do |attr|
96
+ name = attr.split(' ')[0].chop
97
+ attrs[:"#{name}"] = attr.split(' ')[1].to_i
98
+ end
99
+ end
100
+ end
101
+
102
+ # Set default value for i/o attributes in attrs container
103
+ #
104
+ # @param attrs [Hash] hash list contains process attributes
105
+ def process_io_set_nil(attrs)
106
+ ['rchar','wchar','syscr','syscw','read_bytes','write_bytes','cancelled_write_bytes'].each do |attr|
107
+ attrs[:"#{attr}"] = 'Permission denied'
108
+ end
109
+ end
110
+
111
+ # @see https://www.kernel.org/doc/Documentation/filesystems/proc.txt
112
+ # Read statistics from /proc/<pid>/stat file and save in attrs container
113
+ #
114
+ # @example
115
+ # container = Hash.new
116
+ # process_stat(container)
117
+ #
118
+ # @param attrs [Hash] hash list contains process attributes
119
+ def process_stat(attrs)
120
+ stat_file = "/proc/#{attrs[:pid]}/stat"
121
+ if File.readable? (stat_file)
122
+ File.foreach(stat_file).each do |line|
123
+ attr = line.split(' ')
124
+ attrs[:utime] = attr[13].to_i
125
+ attrs[:stime] = attr[14].to_i
126
+ attrs[:cpu_time] = (attrs[:utime] + attrs[:stime])
127
+ attrs[:cpu_percent] = cpu_percent({:cpu_time => attrs[:cpu_time], :proc_uptime => attr[21].to_i })
128
+ end
129
+ end
130
+ end
131
+
132
+ # Get ctime of process from pid file timestamp
133
+ #
134
+ # @example
135
+ # process_ctime(122)
136
+ #
137
+ # @param pid [Fixnum] process pid
138
+ # @return [aTime]
139
+ def process_ctime(pid)
140
+ pid_dir = "/proc/#{pid}"
141
+ (Dir.exist?(pid_dir)) ? File.ctime(pid_dir) : 0
142
+ end
143
+
144
+ # @note read access to cwd file are restricted only to owner of process
145
+ # Get current work directory
146
+ #
147
+ # @example
148
+ # process_cwd(323)
149
+ #
150
+ # @param pid [Fixnum] process pid
151
+ # @return [String]
152
+ def process_cwd(pid)
153
+ cwd_file = "/proc/#{pid}/cwd"
154
+ (File.readable?(cwd_file)) ? File.readlink(cwd_file) : 'Permission denied'
155
+ end
156
+
157
+ # @note read access to io file are restricted only to owner of process
158
+ # Get command line arguments
159
+ #
160
+ # @example
161
+ # process_cmdline(312)
162
+ #
163
+ # @param pid [Fixnum] process pid
164
+ # @return [String]
165
+ def process_cmdline(pid)
166
+ cmdline_file = "/proc/#{pid}/cmdline"
167
+ if File.readable? (cmdline_file)
168
+ File.foreach(cmdline_file).each do |line|
169
+ return line
170
+ end
171
+ else
172
+ 'Permission denied'
173
+ end
174
+ end
175
+
176
+ # Get soft and hard limits for process from limits file
177
+ #
178
+ # @example
179
+ # p = process_limits('312')
180
+ #
181
+ # p.limits.each do |limit|
182
+ # puts "#{limit[name]} #{limit[:soft]} #{limit[:hard]}"
183
+ # end
184
+ #
185
+ # @param pid [Fixnum] process pid
186
+ # @return [Array<Hash>]
187
+ def process_limits(pid)
188
+ limits_file = "/proc/#{pid}/limits"
189
+ limits_list = Array.new
190
+ if File.readable?(limits_file)
191
+ File.foreach(limits_file).each do |line|
192
+ next if (line =~ /Limit/)
193
+ line_split = line.split(' ')
194
+ if line.split(' ')[1] == 'processes'
195
+ lname = "#{line_split[1]}"
196
+ lsoft = "#{line_split[2]} #{line_split[4]}"
197
+ lhard = "#{line_split[3]} #{line_split[4]}"
198
+ else
199
+ lname = "#{line_split[1]}_#{line_split[2]}"
200
+ if line.split(' ')[5]
201
+ lsoft = "#{line_split[3]} #{line_split[5]}"
202
+ lhard = "#{line_split[4]} #{line_split[5]}"
203
+ else
204
+ lsoft = "#{line_split[3]}"
205
+ lhard = "#{line_split[4]}"
206
+ end
207
+ end
208
+ limits_attrs = { :name => "#{lname}", :soft => "#{lsoft}", :hard => "#{lhard}" }
209
+ limits_list << limits_attrs
210
+ end
211
+ else
212
+ limits_list = ['Permission denied']
213
+ end
214
+ limits_list
215
+ end
216
+
217
+ # @note read access to fd directory are restricted only to owner of process
218
+ # Get & set open files and sockets from fd directory in attrs container
219
+ #
220
+ # @param attrs [Hash] hash list contains process attributes
221
+ # @param sockets [Array<Hash>] list sockets from /proc/net/tcp /proc/net/udp file
222
+ def process_files(attrs, sockets)
223
+ fd_dir = "/proc/#{attrs[:pid]}/fd"
224
+ files = Array.new
225
+ ports = Array.new
226
+ if File.readable?(fd_dir)
227
+ Dir.foreach(fd_dir).each do |fd|
228
+ if is_numeric?(fd)
229
+ file = File.readlink("#{fd_dir}/#{fd}")
230
+ attrs[:tty] = file if fd == '0'
231
+ if file =~ /^\// && file !~ /^\/(dev|proc)/
232
+ files << file
233
+ elsif file =~ /socket/
234
+ net_listen = compare_socket(file, sockets)
235
+ if net_listen; ports << net_listen end
236
+ end
237
+ end
238
+ end
239
+ attrs[:open_files] = files
240
+ attrs[:listen_ports] = ports
241
+ else
242
+ attrs[:open_files] = 'Permission denied'
243
+ attrs[:listen_ports] = 'Permission denied'
244
+ attrs[:tty] = 'Permission denied'
245
+ end
246
+ end
247
+
248
+ # Match socket id from /proc/<pid>/fd with /proc/net/(tcp|udp)
249
+ #
250
+ # @return [String] containing matched protocol,ip and port (example: tcp:127.0.0.1:8080)
251
+ def compare_socket(file, sockets)
252
+ sockets.each do |socket|
253
+ return "#{socket[:protocol]}:#{socket[:address]}:#{socket[:port]}" if file =~ /#{socket[:id]}/
254
+ end
255
+ return nil
256
+ end
257
+
258
+ # @note read access to fd directory are restricted only to owner of process
259
+ # Get environment variables from environ file
260
+ #
261
+ # @example
262
+ # process_cmdline(312)
263
+ #
264
+ # @param pid [Fixnum] process pid
265
+ # @return [String]
266
+ def process_env(pid)
267
+ environ_file = "/proc/#{pid}/environ"
268
+ if File.readable? (environ_file)
269
+ File.foreach(environ_file).each do |line|
270
+ return line.split("\x0")
271
+ end
272
+ else
273
+ 'Permission denied'
274
+ end
275
+ end
276
+
277
+ # Calculate %CPU usage per process
278
+ #
279
+ # @param attrs [Hash] hash list contains process attributes
280
+ # @option proc_uptime [Integer] - process uptime
281
+ # @option cpu_time [Integer] total cpu time spend in kernel and user mode
282
+ # @return [Float] average process cpu usage from start
283
+ def cpu_percent(attrs)
284
+ hertz = cpu_tck
285
+ sec = uptime - attrs[:proc_uptime] / hertz
286
+ if attrs[:cpu_time] > 0 && sec > 0
287
+ cpu = (attrs[:cpu_time] * 1000 / hertz) / sec
288
+ "#{cpu / 10}.#{cpu % 10}".to_f
289
+ else
290
+ return 0.0
291
+ end
292
+ end
293
+
294
+ # Check if object is numeric
295
+ #
296
+ # @example
297
+ # is_numeric?('2323')
298
+ #
299
+ # @return [Boolen]
300
+ def is_numeric?(obj)
301
+ obj.to_s.match(/\A[+-]?\d+?(\.\d+)?\Z/) == nil ? false : true
302
+ end
303
+
304
+ # Return the number of clock ticks
305
+ #
306
+ # @example
307
+ # cpu_tck()
308
+ #
309
+ # @return [Integer]
310
+ def cpu_tck
311
+ `getconf CLK_TCK`.to_i
312
+ rescue
313
+ return 100
314
+ end
315
+
316
+ # Get process uid and return username from passwd file
317
+ #
318
+ # @example
319
+ # process_username(132)
320
+ #
321
+ # @param pid [Fixnum] process pid
322
+ # @return [String]
323
+ def process_username(pid)
324
+ uid = File.stat("/proc/#{pid}").uid
325
+ File.foreach('/etc/passwd').each do |line|
326
+ if line.split(':')[2] == "#{uid}"
327
+ return line.split(':')[0]
328
+ end
329
+ end
330
+ end
331
+
332
+ # Get list open tcp/upd ports from net/tcp and net/udp file and replace to decimal
333
+ #
334
+ # @example
335
+ # sockets = open_ports()
336
+ # sockets.each do |socket|
337
+ # puts "#{socket[:address]} #{socket[:port]}"
338
+ # end
339
+ #
340
+ # @return [Array<Hash>] list all used tcp/udp sockets
341
+ def open_ports
342
+ socket_list = Array.new
343
+ ['tcp','udp'].each do |protocol|
344
+ File.foreach("/proc/net/#{protocol}").each do |line|
345
+ hex_port = line.split(' ')[1].split(':')[1]
346
+ hex_ip = line.split(' ')[1].split(':')[0].scan(/../)
347
+ socketid = line.split(' ')[9]
348
+ if hex_port =~ /$$$$/
349
+ hex_ip.map! { |e| e = e.to_i(16) }
350
+ socket_attrs = { :address => "#{hex_ip[3]}.#{hex_ip[2]}.#{hex_ip[1]}.#{hex_ip[0]}",
351
+ :port => hex_port.to_i(16),
352
+ :protocol => protocol,
353
+ :id => socketid }
354
+ socket_list << socket_attrs
355
+ end
356
+ end
357
+ end
358
+ return socket_list
359
+ end
360
+
361
+ # Return system uptime in second
362
+ #
363
+ # @example
364
+ # uptime()
365
+ #
366
+ # @return [Integer]
367
+ def uptime
368
+ File.foreach('/proc/uptime').each do |line|
369
+ return line.split[0].to_i
370
+ end
371
+ end
372
+
373
+ # Calculate percent of memory usage by process
374
+ #
375
+ # @example
376
+ # memory_percent(container,'')
377
+ #
378
+ # @param attrs [Hash] hash list contains process attributes
379
+ # @option :vmrss [Fixnum] rss memory allocated by process
380
+ # @param memtotal [Integer] total usable RAM
381
+ # @return [Float]
382
+ def memory_percent(attrs, memtotal)
383
+ if attrs[:vmrss]
384
+ return (attrs[:vmrss].to_f / memtotal.to_f * 100).round(2)
385
+ else
386
+ nil
387
+ end
388
+ end
389
+
390
+ # Get total physical memory (RAM) size
391
+ #
392
+ # @example
393
+ # memory_total
394
+ #
395
+ # @return [Integer]
396
+ def memory_total
397
+ File.foreach('/proc/meminfo').each do |line|
398
+ return line.split(' ')[1].to_i if line =~ /MemTotal:/
399
+ end
400
+ end
401
+
402
+ end
403
+ end
404
+ end
405
+ end
@@ -0,0 +1,53 @@
1
+ module HawatelPS
2
+ module Linux
3
+ class ProcInfo < ProcControl
4
+
5
+ # Process instance with attributes of that process
6
+ # @param proc_attrs [Hash] attributes of the process
7
+ # @return [void]
8
+ def initialize(proc_attrs)
9
+ @proc_attrs = proc_attrs
10
+ define_attributes(proc_attrs)
11
+ end
12
+
13
+ # Make attributes of public.
14
+ # Access to process attribute from an object instance by index of array.
15
+ # @example
16
+ # p = ProcInfo.new(proc_attrs)
17
+ # puts p['processid']
18
+ def [](key)
19
+ @proc_attrs[key.downcase]
20
+ end
21
+
22
+ # Calls the given block once for each element in self, passing that element as a parameter.
23
+ # @param &block
24
+ # @example print all attributes of process
25
+ # p = ProcInfo.new(proc_attrs)
26
+ # proc.each {|key, val| puts "#{key} - #{val}"}
27
+ # @return An Enumerator is returned if no block is given.
28
+ def each(&block)
29
+ @proc_attrs.each(&block)
30
+ end
31
+
32
+ # @see ProcInfo#define_attributes
33
+ def metaclasses
34
+ class << self; self; end
35
+ end
36
+
37
+ private
38
+ # Make attributes of public.
39
+ # Access to process attribute from an object instance by public method where names of attributes are methods.
40
+ # @example
41
+ # p = ProcInfo.new(proc_attrs)
42
+ # puts p.processid
43
+ def define_attributes(hash)
44
+ hash.each_pair do |key, value|
45
+ metaclasses.send(:attr_reader, key.to_sym)
46
+ instance_variable_set("@#{key}", value)
47
+ end
48
+ end
49
+
50
+
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,124 @@
1
+ module HawatelPS
2
+ module Linux
3
+ class ProcTable
4
+ class << self
5
+
6
+ # Return attributes of searched process based on pid
7
+ #
8
+ # @example
9
+ # search_by_pid(1761)
10
+ #
11
+ # @param [Integer] pid of process
12
+ # @return [ProcInfo] hash with process attributes
13
+ def search_by_pid(pid)
14
+ refresh
15
+ @proc_table.each do |process|
16
+ return process if process.pid.to_s == pid.to_s
17
+ end
18
+ return nil
19
+ end
20
+
21
+ # Return attributes of searched process based on name or cmdline
22
+ #
23
+ # @example
24
+ # search_by_name('java')
25
+ # search_by_name('/^regex/')
26
+ #
27
+ # @param process_name[String] name of process
28
+ # @return [Array<ProcInfo>] array of ProcInfo objects
29
+ def search_by_name(process_name)
30
+ refresh
31
+ process_list = Array.new
32
+ if process_name =~ /^\/.*\/$/
33
+ process_name.slice!(0)
34
+ process_name = Regexp.new(/#{process_name.chop}/)
35
+ end
36
+ @proc_table.each do |process|
37
+ if process_name.is_a? Regexp
38
+ process_list << process if process.name =~ process_name || process.cmdline =~ process_name
39
+ else
40
+ process_list << process if process.name == "#{process_name}" || process.cmdline == "#{process_name}"
41
+ end
42
+ end
43
+ return process_list
44
+ end
45
+
46
+ # Return attributes of searched process based on specified condition
47
+ #
48
+ # @example
49
+ # search_by_condition(:attrs => 'vmsize', :oper => '<', value => '10000')
50
+ #
51
+ # @param args[Hash] attributes for search condition
52
+ # @option :attr [String], name of process attribute (first expression for if)
53
+ # @option :oper [String], operatator, available options: >,<,>=,<=,==,!=
54
+ # @option :value [String], value comparable (second expression for if)
55
+ #
56
+ # @return [Array<ProcInfo>] array of ProcInfo objects
57
+ def search_by_condition(args)
58
+ refresh
59
+ attr = args[:attr]
60
+ oper = args[:oper]
61
+ value = args[:value]
62
+ process_list = Array.new
63
+ @proc_table.each do |process|
64
+ value = value.to_i if process[:"#{attr}"].is_a? Fixnum
65
+ value = value.to_f if process[:"#{attr}"].is_a? Float
66
+ if oper == '>'
67
+ process_list << process if process[:"#{attr}"] > value if process[:"#{attr}"]
68
+ elsif oper == '<'
69
+ process_list << process if process[:"#{attr}"] < value if process[:"#{attr}"]
70
+ elsif oper == '>='
71
+ process_list << process if process[:"#{attr}"] >= value if process[:"#{attr}"]
72
+ elsif oper == '<='
73
+ process_list << process if process[:"#{attr}"] <= value if process[:"#{attr}"]
74
+ elsif oper == '=='
75
+ process_list << process if process[:"#{attr}"] == value if process[:"#{attr}"]
76
+ elsif oper == '!='
77
+ process_list << process if process[:"#{attr}"] != value if process[:"#{attr}"]
78
+ end
79
+ end
80
+ return process_list
81
+ end
82
+
83
+ # Return all process instances
84
+ #
85
+ # @example
86
+ # proc_table()
87
+ #
88
+ # @return [Array<ProcInfo>] array of ProcInfo objects
89
+ def proc_table
90
+ refresh
91
+ return @proc_table
92
+ end
93
+
94
+ private
95
+ # Refresh list of current running processes
96
+ #
97
+ # @example
98
+ # refresh()
99
+ #
100
+ # @return [Array<ProcInfo>] array of ProcInfo objects
101
+ def refresh
102
+ @proc_table = Array.new
103
+ ProcFetch.get_process.each do |proc_attrs|
104
+ @proc_table.push(ProcInfo.new(proc_attrs))
105
+ end
106
+ childs_tree
107
+ end
108
+
109
+ # Find and add childs attribute for process
110
+ #
111
+ def childs_tree
112
+ @proc_table.each do |proc_parent|
113
+ @proc_table.each do |proc_child|
114
+ if proc_parent.pid == proc_child.ppid
115
+ proc_parent[:childs].push(proc_child)
116
+ end
117
+ end
118
+ end
119
+ end
120
+
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,4 @@
1
+ require 'hawatel_ps/linux/proc_control'
2
+ require 'hawatel_ps/linux/proc_fetch'
3
+ require 'hawatel_ps/linux/proc_info'
4
+ require 'hawatel_ps/linux/proc_table'
@@ -0,0 +1,21 @@
1
+ module HawatelPS
2
+ class HawatelPSException < Exception
3
+ # Custom exception
4
+ # @param args [Hash] the options to create a custom exception message
5
+ # @option :exception [Exception] Native Exception object
6
+ # @option :message [String] Custom message
7
+ # @return [void]
8
+ def initialize(args = {:exception => nil, :message => nil})
9
+ super(exception_enrichment(args))
10
+ end
11
+
12
+ private
13
+ def exception_enrichment(args)
14
+ error_message = ''
15
+ error_message += args[:message] unless args[:message].nil?
16
+ error_message +=
17
+ "\nNative exception from '#{args[:exception].class}':\n#{args[:exception].message}" unless args[:exception].nil?
18
+ return error_message
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,3 @@
1
+ module HawatelPs
2
+ VERSION = "0.1.1"
3
+ end
@@ -0,0 +1,67 @@
1
+ module HawatelPS
2
+ module Windows
3
+ class ProcControl
4
+
5
+ # Check current process status
6
+ #
7
+ # @example
8
+ # p = HawatelPS.search_by_name('notepad.exe')
9
+ # p.status
10
+ #
11
+ # @return [String] 'running' or 'not running'
12
+ def status
13
+ Process.kill 0, @proc_attrs[:processid].to_i
14
+ return "running"
15
+ rescue Errno::ESRCH
16
+ return "not running"
17
+ end
18
+
19
+ # Suspend process without loss data
20
+ #
21
+ # @example
22
+ # p = HawatelPS.search_by_pid('1020')
23
+ # p.suspend
24
+ #
25
+ # @return [String]
26
+ def suspend
27
+ # TODO There is no SuspendProcess API function in Windows.
28
+ # This was described in article: http://www.codeproject.com/Articles/2964/Win-process-suspend-resume-tool
29
+ # The suspend method isn't not save
30
+ end
31
+
32
+
33
+ # Resume suspended process
34
+ # @example
35
+ # p = HawatelPS.search_by_pid('1020')
36
+ # p.resume
37
+ # @return [String]
38
+ def resume
39
+ # TODO There is no ResumeProcess API function in Windows.
40
+ # This was described in article: http://www.codeproject.com/Articles/2964/Win-process-suspend-resume-tool
41
+ # The resume method isn't not save
42
+ end
43
+
44
+
45
+ # Terminate process
46
+ # @example
47
+ # p = HawatelPS.search_by_pid('1020')
48
+ # p.terminate
49
+ # @return [Integer] return source: https://msdn.microsoft.com/en-us/library/windows/desktop/aa393907
50
+ # * Successful completion (0)
51
+ # * Process not found (1)
52
+ # * Access denied (2)
53
+ # * Insufficient privilege (3)
54
+ # * Unknown failure (8)
55
+ # * Path not found (9)
56
+ # * Invalid parameter (21)
57
+ # * Other (22–4294967295)
58
+ def terminate
59
+ return @proc_attrs[:wmi_object].Terminate if @proc_attrs[:wmi_object].ole_respond_to?('Terminate')
60
+ rescue WIN32OLERuntimeError => ex
61
+ #raise HawatelPSException, :exception => ex, :message => "Cannot terminate process by WMI method Terminate()."
62
+ return 1
63
+ end
64
+
65
+ end
66
+ end
67
+ end