-
-
Notifications
You must be signed in to change notification settings - Fork 189
/
shell_out.rb
57 lines (46 loc) · 1.18 KB
/
shell_out.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
require 'open3'
class ShellOut
WaitTimeout = Class.new(StandardError)
PROCESS_EXIT = "[PROCESS EXIT]".freeze
def self.command(command, env: {}, &block)
new.command(command, env: env, &block)
end
attr_reader :output
def initialize
@output = Concurrent::Array.new
end
def command(command, env: {})
all_env = ENV.to_h.merge(env)
Open3.popen3(all_env, command, chdir: Rails.root) do |stdin, stdout, stderr, wait_thr|
pid = wait_thr.pid
stdin.close
stdout_future = Concurrent::Promises.future(stdout, @output) do |fstdout, foutput|
loop do
line = fstdout.gets
break unless line
foutput << line
end
end
stderr_future = Concurrent::Promises.future(stderr, @output) do |fstderr, foutput|
loop do
line = fstderr.gets
break unless line
foutput << line
end
end
begin
yield(self)
ensure
begin
Process.kill('TERM', pid)
wait_thr.value
rescue Errno::ESRCH
@output << PROCESS_EXIT
end
end
stdout_future.value
stderr_future.value
@output
end
end
end