foreman 0.26.1 → 0.40.0

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 (41) hide show
  1. data/README.md +40 -0
  2. data/bin/foreman-runner +36 -0
  3. data/data/example/Procfile +1 -0
  4. data/data/example/utf8 +11 -0
  5. data/data/export/bluepill/master.pill.erb +3 -3
  6. data/lib/foreman/cli.rb +35 -31
  7. data/lib/foreman/engine.rb +109 -82
  8. data/lib/foreman/export/base.rb +12 -5
  9. data/lib/foreman/export/bluepill.rb +5 -7
  10. data/lib/foreman/export/inittab.rb +11 -13
  11. data/lib/foreman/export/runit.rb +24 -25
  12. data/lib/foreman/export/upstart.rb +9 -11
  13. data/lib/foreman/export.rb +21 -0
  14. data/lib/foreman/helpers.rb +45 -0
  15. data/lib/foreman/process.rb +88 -6
  16. data/lib/foreman/procfile.rb +8 -7
  17. data/lib/foreman/procfile_entry.rb +22 -0
  18. data/lib/foreman/utils.rb +4 -1
  19. data/lib/foreman/version.rb +1 -1
  20. data/lib/foreman.rb +12 -1
  21. data/man/foreman.1 +17 -3
  22. data/spec/foreman/cli_spec.rb +96 -7
  23. data/spec/foreman/engine_spec.rb +52 -31
  24. data/spec/foreman/export/base_spec.rb +22 -0
  25. data/spec/foreman/export/bluepill_spec.rb +23 -7
  26. data/spec/foreman/export/inittab_spec.rb +40 -0
  27. data/spec/foreman/export/runit_spec.rb +18 -12
  28. data/spec/foreman/export/upstart_spec.rb +40 -8
  29. data/spec/foreman/export_spec.rb +22 -0
  30. data/spec/foreman/helpers_spec.rb +26 -0
  31. data/spec/foreman/process_spec.rb +131 -2
  32. data/spec/foreman_spec.rb +5 -0
  33. data/spec/helper_spec.rb +18 -0
  34. data/spec/resources/bin/utf8 +2 -0
  35. data/spec/resources/export/bluepill/app-concurrency.pill +47 -0
  36. data/spec/resources/export/bluepill/app.pill +1 -22
  37. data/spec/resources/export/inittab/inittab.concurrency +4 -0
  38. data/spec/resources/export/inittab/inittab.default +4 -0
  39. data/spec/spec_helper.rb +36 -4
  40. metadata +23 -11
  41. data/README.markdown +0 -49
data/README.md ADDED
@@ -0,0 +1,40 @@
1
+ # Foreman
2
+
3
+ Manage Procfile-based applications
4
+
5
+ <table>
6
+ <tr>
7
+ <th>If you have...</th>
8
+ <th>Install with...</th>
9
+ </tr>
10
+ <tr>
11
+ <td>Ruby (MRI, JRuby, Windows)</td>
12
+ <td><pre>$ gem install foreman</pre></td>
13
+ </tr>
14
+ <tr>
15
+ <td>Mac OS X</td>
16
+ <td><a href="http://assets.foreman.io/foreman/foreman.pkg">foreman.pkg</a></td>
17
+ </tr>
18
+ </table>
19
+
20
+ ## Getting Started
21
+
22
+ * http://blog.daviddollar.org/2011/05/06/introducing-foreman.html
23
+
24
+ ## Documentation
25
+
26
+ * [man page](http://ddollar.github.com/foreman)
27
+ * [wiki](http://github.com/ddollar/foreman/wiki)
28
+ * [changelog](https://github.com/ddollar/foreman/blob/master/Changelog.md)
29
+
30
+ ## Authors
31
+
32
+ #### Created and maintained by
33
+ David Dollar
34
+
35
+ #### Patches contributed by
36
+ [Contributor List](https://github.com/ddollar/foreman/contributors)
37
+
38
+ ## License
39
+
40
+ MIT
@@ -0,0 +1,36 @@
1
+ #!/bin/sh
2
+ #
3
+ #/ Usage: foreman-runner [-d <dir>] <command>
4
+ #/
5
+ #/ Run a command with exec, optionally changing directory first
6
+
7
+ set -e
8
+
9
+ error() {
10
+ echo $@ >&2
11
+ exit 1
12
+ }
13
+
14
+ usage() {
15
+ cat $0 | grep '^#/' | cut -c4-
16
+ exit
17
+ }
18
+
19
+ while getopts ":hd:" OPT; do
20
+ case $OPT in
21
+ d) cd "$OPTARG" ;;
22
+ h) usage ;;
23
+ \?) error "invalid option: -$OPTARG" ;;
24
+ :) error "option -$OPTARG requires an argument" ;;
25
+ esac
26
+ done
27
+
28
+ shift $((OPTIND-1))
29
+
30
+ command=$1
31
+
32
+ if [ -z "$1" ]; then
33
+ usage
34
+ fi
35
+
36
+ exec $1
@@ -1,2 +1,3 @@
1
1
  ticker: ruby ./ticker $PORT
2
2
  error: ruby ./error
3
+ utf8: ruby ./utf8
data/data/example/utf8 ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: BINARY
3
+
4
+ $stdout.sync = true
5
+
6
+ while true
7
+ puts "\u65e5\u672c\u8a9e\u6587\u5b57\u5217"
8
+ puts "\u0915\u0932\u094d\u0907\u0928\u0643\u0637\u0628\u041a\u0430\u043b\u0438\u043d\u0430"
9
+ puts "\xff\x03"
10
+ sleep 1
11
+ end
@@ -3,9 +3,9 @@ Bluepill.application("<%= app %>", :foreground => false, :log_file => "/var/log/
3
3
  app.uid = "<%= user %>"
4
4
  app.gid = "<%= user %>"
5
5
 
6
- <% engine.processes.each do |process| %>
6
+ <% engine.procfile.entries.each do |process| %>
7
7
  <% 1.upto(concurrency[process.name]) do |num| %>
8
- <% port = engine.port_for(process, num, options[:port]) %>
8
+ <% port = engine.port_for(process, num, self.port) %>
9
9
  app.process("<%= process.name %>-<%=num%>") do |process|
10
10
  process.start_command = "<%= process.command.gsub("$PORT", port.to_s) %>"
11
11
 
@@ -19,7 +19,7 @@ Bluepill.application("<%= app %>", :foreground => false, :log_file => "/var/log/
19
19
  process.monitor_children do |children|
20
20
  children.stop_command "kill -QUIT {{PID}}"
21
21
  end
22
-
22
+
23
23
  process.group = "<%= app %>-<%= process.name %>"
24
24
  end
25
25
  <% end %>
data/lib/foreman/cli.rb CHANGED
@@ -1,27 +1,36 @@
1
1
  require "foreman"
2
+ require "foreman/helpers"
2
3
  require "foreman/engine"
3
4
  require "foreman/export"
4
5
  require "thor"
5
6
  require "yaml"
6
7
 
7
8
  class Foreman::CLI < Thor
9
+ include Foreman::Helpers
8
10
 
9
11
  class_option :procfile, :type => :string, :aliases => "-f", :desc => "Default: Procfile"
10
12
 
11
- desc "start [PROCESS]", "Start the application, or a specific process"
13
+ desc "start [PROCESS]", "Start the application (or a specific PROCESS)"
14
+
15
+ class_option :procfile, :type => :string, :aliases => "-f", :desc => "Default: Procfile"
16
+ class_option :app_root, :type => :string, :aliases => "-d", :desc => "Default: Procfile directory"
12
17
 
13
18
  method_option :env, :type => :string, :aliases => "-e", :desc => "Specify an environment file to load, defaults to .env"
14
19
  method_option :port, :type => :numeric, :aliases => "-p"
15
20
  method_option :concurrency, :type => :string, :aliases => "-c", :banner => '"alpha=5,bar=3"'
16
21
 
22
+ class << self
23
+ # Hackery. Take the run method away from Thor so that we can redefine it.
24
+ def is_thor_reserved_word?(word, type)
25
+ return false if word == 'run'
26
+ super
27
+ end
28
+ end
29
+
17
30
  def start(process=nil)
18
31
  check_procfile!
19
-
20
- if process
21
- engine.execute(process)
22
- else
23
- engine.start
24
- end
32
+ engine.options[:concurrency] = "#{process}=1" if process
33
+ engine.start
25
34
  end
26
35
 
27
36
  desc "export FORMAT LOCATION", "Export the application to another process management format"
@@ -32,22 +41,12 @@ class Foreman::CLI < Thor
32
41
  method_option :port, :type => :numeric, :aliases => "-p"
33
42
  method_option :user, :type => :string, :aliases => "-u"
34
43
  method_option :template, :type => :string, :aliases => "-t"
35
- method_option :concurrency, :type => :string, :aliases => "-c",
36
- :banner => '"alpha=5,bar=3"'
44
+ method_option :concurrency, :type => :string, :aliases => "-c", :banner => '"alpha=5,bar=3"'
37
45
 
38
46
  def export(format, location=nil)
39
47
  check_procfile!
40
-
41
- formatter = case format
42
- when "inittab" then Foreman::Export::Inittab
43
- when "upstart" then Foreman::Export::Upstart
44
- when "bluepill" then Foreman::Export::Bluepill
45
- when "runit" then Foreman::Export::Runit
46
- else error "Unknown export format: #{format}."
47
- end
48
-
49
- formatter.new(engine).export(location, options)
50
-
48
+ formatter = Foreman::Export.formatter(format)
49
+ formatter.new(location, engine, options).export
51
50
  rescue Foreman::Export::Exception => ex
52
51
  error ex.message
53
52
  end
@@ -55,8 +54,22 @@ class Foreman::CLI < Thor
55
54
  desc "check", "Validate your application's Procfile"
56
55
 
57
56
  def check
58
- error "no processes defined" unless engine.processes.length > 0
59
- display "valid procfile detected (#{engine.processes.map(&:name).join(', ')})"
57
+ check_procfile!
58
+ error "no processes defined" unless engine.procfile.entries.length > 0
59
+ puts "valid procfile detected (#{engine.procfile.process_names.join(', ')})"
60
+ end
61
+
62
+ desc "run COMMAND", "Run a command using your application's environment"
63
+
64
+ def run(*args)
65
+ engine.apply_environment!
66
+ begin
67
+ exec args.join(" ")
68
+ rescue Errno::EACCES
69
+ error "not executable: #{args.first}"
70
+ rescue Errno::ENOENT
71
+ error "command not found: #{args.first}"
72
+ end
60
73
  end
61
74
 
62
75
  private ######################################################################
@@ -73,24 +86,15 @@ private ######################################################################
73
86
  options[:procfile] || "Procfile"
74
87
  end
75
88
 
76
- def display(message)
77
- puts message
78
- end
79
-
80
89
  def error(message)
81
90
  puts "ERROR: #{message}"
82
91
  exit 1
83
92
  end
84
93
 
85
- def procfile_exists?(procfile)
86
- File.exist?(procfile)
87
- end
88
-
89
94
  def options
90
95
  original_options = super
91
96
  return original_options unless File.exists?(".foreman")
92
97
  defaults = YAML::load_file(".foreman") || {}
93
98
  Thor::CoreExt::HashWithIndifferentAccess.new(defaults.merge(original_options))
94
99
  end
95
-
96
100
  end
@@ -2,146 +2,151 @@ require "foreman"
2
2
  require "foreman/process"
3
3
  require "foreman/procfile"
4
4
  require "foreman/utils"
5
- require "pty"
6
5
  require "tempfile"
7
6
  require "timeout"
8
7
  require "term/ansicolor"
9
8
  require "fileutils"
9
+ require "thread"
10
10
 
11
11
  class Foreman::Engine
12
12
 
13
+ attr_reader :environment
13
14
  attr_reader :procfile
14
15
  attr_reader :directory
15
- attr_reader :environment
16
16
  attr_reader :options
17
17
 
18
18
  extend Term::ANSIColor
19
19
 
20
- COLORS = [ cyan, yellow, green, magenta, red ]
20
+ COLORS = [ cyan, yellow, green, magenta, red, blue,
21
+ intense_cyan, intense_yellow, intense_green, intense_magenta,
22
+ intense_red, intense_blue ]
21
23
 
22
24
  def initialize(procfile, options={})
23
25
  @procfile = Foreman::Procfile.new(procfile)
24
- @directory = File.expand_path(File.dirname(procfile))
25
- @options = options
26
+ @directory = options[:app_root] || File.expand_path(File.dirname(procfile))
27
+ @options = options.dup
26
28
  @environment = read_environment_files(options[:env])
29
+ @output_mutex = Mutex.new
27
30
  end
28
31
 
29
32
  def start
30
33
  proctitle "ruby: foreman master"
31
- termtitle "#{File.basename(@directory)} - foreman (#{processes.size} processes)"
32
-
33
- processes.each do |process|
34
- process.color = next_color
35
- fork process
36
- end
37
-
38
- trap("TERM") { puts "SIGTERM received"; terminate_gracefully }
39
- trap("INT") { puts "SIGINT received"; terminate_gracefully }
40
-
41
- watch_for_termination
42
- end
43
-
44
- def execute(name)
45
- error "no such process: #{name}" unless process = procfile[name]
46
- process.color = next_color
47
- fork process
34
+ termtitle "#{File.basename(@directory)} - foreman"
48
35
 
49
36
  trap("TERM") { puts "SIGTERM received"; terminate_gracefully }
50
37
  trap("INT") { puts "SIGINT received"; terminate_gracefully }
51
38
 
39
+ assign_colors
40
+ spawn_processes
41
+ watch_for_output
52
42
  watch_for_termination
53
43
  end
54
44
 
55
- def processes
56
- procfile.processes
57
- end
58
-
59
45
  def port_for(process, num, base_port=nil)
60
46
  base_port ||= 5000
61
47
  offset = procfile.process_names.index(process.name) * 100
62
48
  base_port.to_i + offset + num - 1
63
49
  end
64
50
 
65
- private ######################################################################
66
-
67
- def fork(process)
68
- concurrency = Foreman::Utils.parse_concurrency(@options[:concurrency])
69
-
70
- 1.upto(concurrency[process.name]) do |num|
71
- fork_individual(process, num, port_for(process, num, @options[:port]))
72
- end
51
+ def apply_environment!
52
+ environment.each { |k,v| ENV[k] = v }
73
53
  end
74
54
 
75
- def fork_individual(process, num, port)
76
- @environment.each { |k,v| ENV[k] = v }
55
+ private ######################################################################
77
56
 
78
- ENV["PORT"] = port.to_s
79
- ENV["PS"] = "#{process.name}.#{num}"
57
+ def spawn_processes
58
+ concurrency = Foreman::Utils.parse_concurrency(@options[:concurrency])
80
59
 
81
- pid = Process.fork do
82
- run(process)
60
+ procfile.entries.each do |entry|
61
+ reader, writer = (IO.method(:pipe).arity == 0 ? IO.pipe : IO.pipe("BINARY"))
62
+ entry.spawn(concurrency[entry.name], writer, @directory, @environment, port_for(entry, 1, base_port)).each do |process|
63
+ running_processes[process.pid] = process
64
+ readers[process] = reader
65
+ end
83
66
  end
84
-
85
- info "started with pid #{pid}", process
86
- running_processes[pid] = process
87
67
  end
88
68
 
89
- def run(process)
90
- proctitle "ruby: foreman #{process.name}"
91
- trap("SIGINT", "IGNORE")
92
-
93
- begin
94
- Dir.chdir directory do
95
- PTY.spawn(process.command) do |stdin, stdout, pid|
96
- trap("SIGTERM") { Process.kill("SIGTERM", pid) }
97
- until stdin.eof?
98
- info stdin.gets, process
99
- end
100
- end
101
- end
102
- rescue PTY::ChildExited, Interrupt, Errno::EIO, Errno::ENOENT
103
- begin
104
- info "process exiting", process
105
- rescue Interrupt
106
- end
107
- end
69
+ def base_port
70
+ options[:port] || 5000
108
71
  end
109
72
 
110
73
  def kill_all(signal="SIGTERM")
111
74
  running_processes.each do |pid, process|
112
- Process.kill(signal, pid) rescue Errno::ESRCH
75
+ info "sending #{signal} to pid #{pid}"
76
+ process.kill signal
113
77
  end
114
78
  end
115
79
 
116
80
  def terminate_gracefully
81
+ return if @terminating
82
+ @terminating = true
117
83
  info "sending SIGTERM to all processes"
118
84
  kill_all "SIGTERM"
119
- Timeout.timeout(3) { Process.waitall }
85
+ Timeout.timeout(5) do
86
+ while running_processes.length > 0
87
+ pid, status = Process.wait2
88
+ process = running_processes.delete(pid)
89
+ info "process terminated", process.name
90
+ end
91
+ end
120
92
  rescue Timeout::Error
121
93
  info "sending SIGKILL to all processes"
122
94
  kill_all "SIGKILL"
123
95
  end
124
96
 
97
+ def poll_readers
98
+ rs, ws = IO.select(readers.values, [], [], 1)
99
+ (rs || []).each do |r|
100
+ data = r.gets
101
+ next unless data
102
+ data.force_encoding("BINARY") if data.respond_to?(:force_encoding)
103
+ ps, message = data.split(",", 2)
104
+ color = colors[ps.split(".").first]
105
+ info message, ps, color
106
+ end
107
+ end
108
+
109
+ def watch_for_output
110
+ Thread.new do
111
+ require "win32console" if Foreman.windows?
112
+ begin
113
+ loop do
114
+ poll_readers
115
+ end
116
+ rescue Exception => ex
117
+ puts ex.message
118
+ puts ex.backtrace
119
+ end
120
+ end
121
+ end
122
+
125
123
  def watch_for_termination
126
124
  pid, status = Process.wait2
127
125
  process = running_processes.delete(pid)
128
- info "process terminated", process
126
+ info "process terminated", process.name
129
127
  terminate_gracefully
130
- kill_all
131
128
  rescue Errno::ECHILD
132
129
  end
133
130
 
134
- def info(message, process=nil)
135
- print process.color if process
136
- print "#{Time.now.strftime("%H:%M:%S")} #{pad_process_name(process)} | "
137
- print Term::ANSIColor.reset
138
- print message.chomp
139
- puts
131
+ def info(message, name="system", color=Term::ANSIColor.white)
132
+ output = ""
133
+ output += color
134
+ output += "#{Time.now.strftime("%H:%M:%S")} #{pad_process_name(name)} | "
135
+ output += Term::ANSIColor.reset
136
+ output += message.chomp
137
+ puts output
140
138
  end
141
139
 
142
- def error(message)
143
- puts "ERROR: #{message}"
144
- exit 1
140
+ def print(message=nil)
141
+ @output_mutex.synchronize do
142
+ $stdout.print message
143
+ end
144
+ end
145
+
146
+ def puts(message=nil)
147
+ @output_mutex.synchronize do
148
+ $stdout.puts message
149
+ end
145
150
  end
146
151
 
147
152
  def longest_process_name
@@ -152,9 +157,8 @@ private ######################################################################
152
157
  end
153
158
  end
154
159
 
155
- def pad_process_name(process)
156
- name = process ? "#{ENV["PS"]}" : "system"
157
- name.ljust(longest_process_name + 3) # add 3 for process number padding
160
+ def pad_process_name(name="system")
161
+ name.to_s.ljust(longest_process_name + 3) # add 3 for process number padding
158
162
  end
159
163
 
160
164
  def proctitle(title)
@@ -162,17 +166,36 @@ private ######################################################################
162
166
  end
163
167
 
164
168
  def termtitle(title)
165
- printf("\033]0;#{title}\007")
169
+ printf("\033]0;#{title}\007") unless Foreman.windows?
166
170
  end
167
171
 
168
172
  def running_processes
169
173
  @running_processes ||= {}
170
174
  end
171
175
 
176
+ def readers
177
+ @readers ||= {}
178
+ end
179
+
180
+ def colors
181
+ @colors ||= {}
182
+ end
183
+
184
+ def assign_colors
185
+ procfile.entries.each do |entry|
186
+ colors[entry.name] = next_color
187
+ end
188
+ end
189
+
190
+ def process_by_reader(reader)
191
+ readers.invert[reader]
192
+ end
193
+
172
194
  def next_color
173
195
  @current_color ||= -1
174
196
  @current_color += 1
175
- @current_color >= COLORS.length ? "" : COLORS[@current_color]
197
+ @current_color = 0 if COLORS.length < @current_color
198
+ COLORS[@current_color]
176
199
  end
177
200
 
178
201
  def read_environment_files(filenames)
@@ -192,10 +215,14 @@ private ######################################################################
192
215
 
193
216
  File.read(filename).split("\n").inject({}) do |hash, line|
194
217
  if line =~ /\A([A-Za-z_0-9]+)=(.*)\z/
195
- hash[$1] = $2
218
+ key, val = [$1, $2]
219
+ case val
220
+ when /\A'(.*)'\z/ then hash[key] = $1
221
+ when /\A"(.*)"\z/ then hash[key] = $1.gsub(/\\(.)/, '\1')
222
+ else hash[key] = val
223
+ end
196
224
  end
197
225
  hash
198
226
  end
199
227
  end
200
-
201
228
  end
@@ -3,10 +3,17 @@ require "foreman/utils"
3
3
 
4
4
  class Foreman::Export::Base
5
5
 
6
- attr_reader :engine
7
-
8
- def initialize(engine)
9
- @engine = engine
6
+ attr_reader :location, :engine, :app, :log, :port, :user, :template, :concurrency
7
+
8
+ def initialize(location, engine, options={})
9
+ @location = location
10
+ @engine = engine
11
+ @app = options[:app]
12
+ @log = options[:log]
13
+ @port = options[:port]
14
+ @user = options[:user]
15
+ @template = options[:template]
16
+ @concurrency = Foreman::Utils.parse_concurrency(options[:concurrency])
10
17
  end
11
18
 
12
19
  def export
@@ -26,7 +33,7 @@ private ######################################################################
26
33
  def export_template(exporter, file, template_root)
27
34
  if template_root && File.exist?(file_path = File.join(template_root, file))
28
35
  File.read(file_path)
29
- elsif File.exist?(file_path = File.join("~/.foreman/templates", file))
36
+ elsif File.exist?(file_path = File.expand_path(File.join("~/.foreman/templates", file)))
30
37
  File.read(file_path)
31
38
  else
32
39
  File.read(File.expand_path("../../../../data/export/#{exporter}/#{file}", __FILE__))
@@ -3,23 +3,21 @@ require "foreman/export"
3
3
 
4
4
  class Foreman::Export::Bluepill < Foreman::Export::Base
5
5
 
6
- def export(location, options={})
6
+ def export
7
7
  error("Must specify a location") unless location
8
8
 
9
9
  FileUtils.mkdir_p location
10
10
 
11
- app = options[:app] || File.basename(engine.directory)
12
- user = options[:user] || app
13
- log_root = options[:log] || "/var/log/#{app}"
14
- template_root = options[:template]
11
+ app = self.app || File.basename(engine.directory)
12
+ user = self.user || app
13
+ log_root = self.log || "/var/log/#{app}"
14
+ template_root = self.template
15
15
 
16
16
  Dir["#{location}/#{app}.pill"].each do |file|
17
17
  say "cleaning up: #{file}"
18
18
  FileUtils.rm(file)
19
19
  end
20
20
 
21
- concurrency = Foreman::Utils.parse_concurrency(options[:concurrency])
22
-
23
21
  master_template = export_template("bluepill", "master.pill.erb", template_root)
24
22
  master_config = ERB.new(master_template).result(binding)
25
23
  write_file "#{location}/#{app}.pill", master_config
@@ -2,20 +2,18 @@ require "foreman/export"
2
2
 
3
3
  class Foreman::Export::Inittab < Foreman::Export::Base
4
4
 
5
- def export(fname=nil, options={})
6
- app = options[:app] || File.basename(engine.directory)
7
- user = options[:user] || app
8
- log_root = options[:log] || "/var/log/#{app}"
9
-
10
- concurrency = Foreman::Utils.parse_concurrency(options[:concurrency])
5
+ def export
6
+ app = self.app || File.basename(engine.directory)
7
+ user = self.user || app
8
+ log_root = self.log || "/var/log/#{app}"
11
9
 
12
10
  inittab = []
13
11
  inittab << "# ----- foreman #{app} processes -----"
14
12
 
15
- engine.processes.inject(1) do |index, process|
16
- 1.upto(concurrency[process.name]) do |num|
13
+ engine.procfile.entries.inject(1) do |index, process|
14
+ 1.upto(self.concurrency[process.name]) do |num|
17
15
  id = app.slice(0, 2).upcase + sprintf("%02d", index)
18
- port = engine.port_for(process, num, options[:port])
16
+ port = engine.port_for(process, num, self.port)
19
17
  inittab << "#{id}:4:respawn:/bin/su - #{user} -c 'PORT=#{port} #{process.command} >> #{log_root}/#{process.name}-#{num}.log 2>&1'"
20
18
  index += 1
21
19
  end
@@ -26,12 +24,12 @@ class Foreman::Export::Inittab < Foreman::Export::Base
26
24
 
27
25
  inittab = inittab.join("\n") + "\n"
28
26
 
29
- if fname
27
+ if location == "-"
28
+ puts inittab
29
+ else
30
30
  FileUtils.mkdir_p(log_root) rescue error "could not create #{log_root}"
31
31
  FileUtils.chown(user, nil, log_root) rescue error "could not chown #{log_root} to #{user}"
32
- write_file(fname, inittab)
33
- else
34
- puts inittab
32
+ write_file(location, inittab)
35
33
  end
36
34
  end
37
35