forked from ddollar/foreman
-
Notifications
You must be signed in to change notification settings - Fork 0
/
process.rb
132 lines (118 loc) · 3.2 KB
/
process.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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
require "foreman"
require "rubygems"
class Foreman::Process
attr_reader :command
attr_reader :env
attr_reader :ports
# Create a Process
#
# @param [String] command The command to run
# @param [Hash] options
#
# @option options [String] :cwd (./) Change to this working directory before executing the process
# @option options [Hash] :env ({}) Environment variables to set for this process
#
def initialize(command, options={})
@command = command
@options = options.dup
@options[:env] ||= {}
# parse list of ports needed for this command
@ports = @command.scan(/\$(PORT[0-9]?)/)
@ports = [ "PORT" ] if @ports.length == 0
@ports = @ports.flatten.uniq
end
# Get environment-expanded command for a +Process+
#
# @param [Hash] custom_env ({}) Environment variables to merge with defaults
#
# @return [String] The expanded command
#
def expanded_command(custom_env={})
env = @options[:env].merge(custom_env)
expanded_command = command.dup
env.each do |key, val|
expanded_command.gsub!("$#{key}", val)
end
expanded_command
end
# Run a +Process+
#
# @param [Hash] options
#
# @option options :env ({}) Environment variables to set for this execution
# @option options :output ($stdout) The output stream
#
# @returns [Fixnum] pid The +pid+ of the process
#
def run(options={})
env = @options[:env].merge(options[:env] || {})
output = options[:output] || $stdout
if Foreman.windows?
Dir.chdir(cwd) do
Process.spawn env, expanded_command(env), :out => output, :err => output
end
elsif Foreman.jruby?
require "posix/spawn"
wrapped_command = "#{Foreman.runner} -d '#{cwd}' -p -- #{command}"
POSIX::Spawn.spawn env, wrapped_command, :out => output, :err => output
elsif Foreman.ruby_18?
fork do
$stdout.reopen output
$stderr.reopen output
env.each { |k,v| ENV[k] = v }
wrapped_command = "#{Foreman.runner} -d '#{cwd}' -p -- #{command}"
Kernel.exec wrapped_command
end
else
wrapped_command = "#{Foreman.runner} -d '#{cwd}' -p -- #{command}"
Process.spawn env, wrapped_command, :out => output, :err => output
end
end
# Exec a +Process+
#
# @param [Hash] options
#
# @option options :env ({}) Environment variables to set for this execution
#
# @return Does not return
def exec(options={})
env = @options[:env].merge(options[:env] || {})
env.each { |k, v| ENV[k] = v }
Dir.chdir(cwd)
Kernel.exec expanded_command(env)
end
# Send a signal to this +Process+
#
# @param [String] signal The signal to send
#
def kill(signal)
if Foreman.windows?
pid && Process.kill(signal, pid)
else
pid && Process.kill("-#{signal}", pid)
end
rescue Errno::ESRCH
false
end
# Test whether or not this +Process+ is still running
#
# @returns [Boolean]
#
def alive?
kill(0)
end
# Test whether or not this +Process+ has terminated
#
# @returns [Boolean]
#
def dead?
!alive?
end
# Returns the working directory for this +Process+
#
# @returns [String]
#
def cwd
File.expand_path(@options[:cwd] || ".")
end
end