Compare commits

..

108 Commits

Author SHA1 Message Date
David Dollar
0da42cf7d2 0.63.0 2013-04-15 15:33:51 -04:00
David Dollar
23561b963c fix dotenv dependency 2013-04-15 15:32:27 -04:00
David Dollar
cc51ab2cb1 fix up tests 2013-04-15 15:32:22 -04:00
David Dollar
403d40b277 Revert "Merge pull request #292 from andrewsmedina/master"
Does not pass tests

This reverts commit 17a8a316b8, reversing
changes made to 9e1d590734.
2013-04-15 15:31:38 -04:00
David Dollar
f1c2347680 Merge pull request #317 from andymorris/fix_deleted_upstart_files
Prevent upstart export from deleting similarly named upstart files
2013-04-14 08:45:21 -07:00
David Dollar
80f8242b11 Merge pull request #316 from avtobiff/add-mit-license
Add MIT license text
2013-04-14 08:43:41 -07:00
David Dollar
383276bb79 Merge pull request #343 from steakknife/fix__issue_341__profile_not_found
Fixes #341 . .profile not found error
2013-04-14 08:41:58 -07:00
David Dollar
5a7692ff2c Merge pull request #326 from pje/patch-1
Update man/foreman.1
2013-04-14 08:40:50 -07:00
David Dollar
405a85bc86 Merge pull request #351 from GreenplumChorus/master
Remove posix-spawn dependency for JRuby
2013-04-14 08:40:10 -07:00
David Dollar
bff554d554 Merge pull request #347 from bkeepers/dotenv
Replace Foreman::Env with dotenv
2013-04-14 08:37:31 -07:00
David Dollar
eaed989c75 Merge pull request #329 from kentaro/permit-underscore-in-procfile
Permit hyphen for command name in Procfile
2013-04-14 08:32:24 -07:00
David Dollar
93daebbf1b Merge pull request #323 from dplummer/remove-tmux-from-man
Remove tmux option from man page
2013-04-14 08:31:40 -07:00
David Dollar
17a8a316b8 Merge pull request #292 from andrewsmedina/master
circus support
2013-04-14 08:30:17 -07:00
David Dollar
9e1d590734 Merge pull request #266 from messick/master
Use runlevels in upstart config so app starts after boot in Ubuntu 12.03
2013-04-14 08:28:08 -07:00
David Dollar
1cb1c8812a Merge pull request #352 from john-griffin/master
Restore ability to trap crtl+c
2013-04-11 07:59:52 -07:00
John Griffin
6786f4df39 Revert "Ensure foreman is the process group leader"
This reverts commit 44726e377e.

Conflicts:

	lib/foreman/engine.rb
2013-04-09 17:05:16 +01:00
Andrew Brown & Corey Downing
0be08a0651 remove posix-spawn dependency as it does not work in jruby 1.7.3 2013-04-04 17:27:31 -07:00
Brandon Keepers
3abe10e5ab Replace Foreman::Env with dotenv 2013-03-22 10:38:58 -04:00
Barry Allard
66ab0f08e7 [foreman-runner] fix sourcing as . is rarely in PATH 2013-03-16 00:04:57 -07:00
David Dollar
7be4375168 changelog 2013-03-08 14:53:56 -05:00
David Dollar
2ebb33e049 0.62.0 2013-03-08 14:52:50 -05:00
David Dollar
9fe7ddb8bd Merge pull request #334 from ged/reentrant_signal_handlers
Add deferred signal-handling (fixes #332).
2013-03-08 11:41:12 -08:00
David Dollar
f954a42ecb Merge pull request #335 from ged/20_encoding_fix
Fix spec encoding problem under Ruby 2.0.0.
2013-03-08 11:40:50 -08:00
Michael Granger
169188376b Try to allow children to shut down gracefully
Since signals will no longer be handled once foreman goes into
`terminate_gracefully`, default signal handlers are restored so as
not to cause it to get stuck in an unTERMable state.

This necessitates not using the process group for signalling
except as a last resort, as foreman itself will receive the signals
it sends. This splits `killall` into two methods, one which
signals only processes foreman itself has started, and one which
signals all processes in the process group to try to clean up
more aggressively, and then reworks `terminate_gracefully` to use
them.
2013-03-04 14:05:53 -08:00
Michael Granger
5ab08c608b Add deferred signal-handling (fixes #332).
This uses a thread-local queue and a self-pipe so the code in the
trap blocks is properly re-entrant.

For details, see:

  * http://cr.yp.to/docs/selfpipe.html
  * http://blog.rubybestpractices.com/posts/ewong/016-Implementing-Signal-Handlers.html
2013-03-04 13:28:37 -08:00
Michael Granger
0b5c1f919e Fix spec encoding problem under Ruby 2.0.0. 2013-03-04 13:03:13 -08:00
David Dollar
c94aa13b06 add ruby 2.0 to travis 2013-03-04 13:11:05 -05:00
Kentaro Kuribayashi
8d1e3a849f Fixed specs to pass. 2013-02-21 11:52:37 +09:00
Kentaro Kuribayashi
5ef8bbdbe3 Permit underscore for command name in Procfile. 2013-02-21 11:30:59 +09:00
David Dollar
4e84b92536 Merge pull request #327 from patheticpat/master
Fixed a typo in cli options description
2013-02-14 06:23:57 -08:00
Michael Kaiser
6215f8b3db Fixed a typo in cli options description 2013-02-14 14:45:44 +01:00
Patrick Ellis
8cf5896c3e Update man/foreman.1
fix man example typo: Procfile flag is `-f`, not `-p`
2013-02-05 16:29:38 -08:00
Donald Plummer
5f8032cac8 Remove tmux option from man page
Not well supported at this time. See issue #242
2013-01-30 09:29:16 -08:00
Andy Morris
9f3b903085 Prevent upstart export from deleting similarly named upstart files 2013-01-25 00:24:04 -06:00
Per Andersson
69d278d864 Add MIT license text 2013-01-22 10:10:41 +01:00
David Dollar
ba9167152c handled by mingw now 2013-01-14 08:21:40 -05:00
David Dollar
f31ff18191 update docs 2013-01-14 08:19:40 -05:00
David Dollar
c42110e438 update changelog 2013-01-14 08:19:31 -05:00
David Dollar
26bb0ed54e 0.61.0 2013-01-14 08:18:05 -05:00
David Dollar
44002953f6 Merge pull request #277 from pcasaretto/add-timeout-switch
Add timeout switch to CLI - fixes #178
2013-01-14 05:12:12 -08:00
David Dollar
bb2c3a2d04 Merge pull request #264 from asanghi/master
shared_path is set in documentation leading to early evaluation
2013-01-14 05:10:47 -08:00
David Dollar
88cdaacc67 Merge pull request #258 from mclazarus/master
Don't quote shell escaped values.
2013-01-14 05:10:36 -08:00
David Dollar
faf7b3c40f Merge pull request #279 from evanj/master
Fix --directory option: its actually --root
2013-01-14 05:10:11 -08:00
David Dollar
21dd610eaf Merge pull request #280 from BIAINC/windows/host-support
Strip Windows Line Endings
2013-01-14 05:10:01 -08:00
David Dollar
fe65c7510d Merge pull request #288 from crohr/remove-rubygems-requirement
Remove explicit requirement on rubygems.
2013-01-14 05:08:27 -08:00
David Dollar
cd2c255296 Merge pull request #291 from liveh2o/master
JRuby 1.9 doesn't require posix/spawn
2013-01-14 05:08:10 -08:00
David Dollar
92c1909217 Merge pull request #300 from mattv/output-blank-lines
Don't ignore blank lines in the output
2013-01-14 05:07:31 -08:00
David Dollar
af57bf3d52 Merge pull request #302 from ctrochalakis/process_group_fix
Ensure foreman is the process group leader
2013-01-14 05:07:21 -08:00
David Dollar
443994d3b5 Merge pull request #303 from fxposter/master
Fix for high CPU load. Fixes #260 and #299.
2013-01-14 05:06:44 -08:00
David Dollar
2faa3fb6ff Merge pull request #313 from sonots/fix_color
Fix color bug: not intense_cyan but bright_cyan
2013-01-14 05:02:52 -08:00
nseo
0d53f6bd6c fix more 2013-01-13 22:10:12 +09:00
nseo
1d2bcdbc56 fix color 2013-01-12 01:10:25 +09:00
Pavel Forkert
aceea1472a Fix #299 and #260
Some processes close their output channels and IO.select keeps
returning them as "readable", while IO#gets returns nil on them, thus
spending a lot of CPU looping through the same reader continuously
2013-01-07 02:30:56 +02:00
Christos Trochalakis
44726e377e Ensure foreman is the process group leader
Foreman should be the process leader before killing processes using
his process group id.

Before that foreman was broken when it was not spawned from a shell.
2012-12-27 15:47:02 +02:00
Matt Venables
61eca5a1d8 Don't ignore blank lines in the output
This fixes the stdout code to ensure that empty lines are outputted.
Many times, these blank lines are intentional, so foreman should not
suppress them.

This fixes #286
2012-12-21 11:12:52 -05:00
David Dollar
553ac7f81f Merge pull request #295 from petedmarsh/master
Add license to gemspec
2012-12-03 05:56:14 -08:00
petedmarsh
6790cf02a9 Add license to gemspec 2012-12-03 13:52:27 +00:00
Andrews Medina
9325f2ca6d add circus support 2012-11-29 00:15:01 -02:00
Adam Hutchison
7ad41da592 Since JRuby 1.9 doesn't require posix/spawn, only follow that path if JRuby is loaded and running in 1.8 mode. 2012-11-27 22:07:50 -07:00
Cyril Rohr
8ee7b7afdf Remove explicit requirement on rubygems.
It's better to not force the use of a package manager. Better to add it
to the global RUBYOPT if needed. Also, this fixes a dependency issue
when using the .deb package (rubygems1.9.1 is not required, and should
not be).
2012-11-12 21:10:10 +01:00
Aditya Sanghi
2620b90808 Dont use shared_path variable before multistage has a chance at it 2012-11-02 14:04:27 +05:30
Paul Morton
89bdc3ab8e Strip Windows Line Endings 2012-10-18 09:28:39 -07:00
Evan Jones
60a11eb981 Fix man page: --directory is actually --root. 2012-10-18 11:48:50 -04:00
Paulo Luis Franchini Casaretto
61c222deb8 Add timeout switch to CLI 2012-10-17 16:05:10 -03:00
David Dollar
8fe86e98c8 update docs 2012-10-08 10:47:40 -04:00
David Dollar
5c1ffdb7dc changelog 2012-10-08 10:47:21 -04:00
David Dollar
8b49256175 0.60.2 2012-10-08 10:47:00 -04:00
David Dollar
37d777f224 update docs 2012-10-08 10:46:34 -04:00
David Dollar
73fc059634 Merge pull request #273 from silviorelli/master
Fix for fix on issue #260
2012-10-08 07:46:16 -07:00
Silvio Relli
f7b7029cc0 Fix for nil value on io select loop, fixes #260 2012-10-08 16:40:37 +02:00
David Dollar
3a101ec7dd update changelog 2012-10-08 10:31:10 -04:00
David Dollar
6c931ea15e 0.60.1 2012-10-08 10:30:25 -04:00
David Dollar
d173570d98 ree is timing out 2012-10-08 10:29:37 -04:00
David Dollar
0cd41fee7f Merge pull request #272 from silviorelli/master
High cpu load patch by @mauricio - fixes #260
2012-10-08 07:29:31 -07:00
Silvio Relli
9da4e38209 Cleaner fix for high cpu load issue, fixes #260 2012-10-08 16:05:20 +02:00
Silvio Relli
5d9dfd294e Patch for high cpu load issue 2012-10-08 11:52:39 +02:00
David Dollar
8998e9a47c update docs 2012-09-25 12:39:17 -05:00
David Dollar
8238a86942 update changelog 2012-09-25 12:38:45 -05:00
David Dollar
1153fb0f0c 0.60.0 2012-09-25 12:38:01 -05:00
David Dollar
f69c755d9a Merge pull request #262 from dpiddy/foreman-run-from-procfile
foreman run can run things from the Procfile like heroku run.
2012-09-25 10:37:25 -07:00
Nick Messick
9a91e5df44 use "start|stop\ on runlevel [x]" for upstart config 2012-09-24 18:18:05 -07:00
David Dollar
64f0749d16 0.59.0 2012-09-15 11:49:46 +09:00
David Dollar
6b77ca1e46 Merge pull request #246 from jeremyevans/patch-1
Don't have foreman-runner depend on bash
2012-09-14 19:48:03 -07:00
Kevin McAllister
8fbee31a2d Remove expectation of double quotes around environment variables from
test comparisons
2012-09-14 21:33:57 -04:00
Kevin McAllister
7b4eabf0c5 Remove explicit wrapping of Shellwords.escape in double quotes
According to http://www.ruby-doc.org/stdlib-1.9.3/libdoc/shellwords/rdoc/Shellwords.html#method-c-shellescape

"Note that a resulted string should be used unquoted and is not
intended for use in double quotes nor in single quotes."
2012-09-14 21:33:57 -04:00
Jeremy Evans
6a44dd3fd3 Use /bin/sh instead of bash for foreman-runner
/bin/sh should be installed by default on all unix machines, bash
is not necessarily installed on all machines.
2012-09-14 17:35:54 -07:00
Dan Peterson
e99f3173ef foreman run can run things from the Procfile like heroku run. 2012-09-14 10:43:03 -03:00
David Dollar
6c04dab649 0.58.0 2012-09-14 18:10:05 +09:00
David Dollar
96e26e7412 dont set HOME 2012-09-14 17:44:32 +09:00
David Dollar
a2c03cc402 Merge pull request #217 from danielfarrell/capistrano
Add capistrano export support
2012-09-14 01:42:34 -07:00
David Dollar
803115c0c4 Merge pull request #226 from alachaum/master
CLI: fix directory option
2012-09-14 01:41:36 -07:00
David Dollar
a4343187ad Merge pull request #239 from indrekj/master
Use path and env variables in the inittab export
2012-09-14 01:41:18 -07:00
David Dollar
98af1f0943 Merge pull request #261 from martinisoft/launchd_environment
Launchd environment
2012-09-14 01:34:35 -07:00
David Dollar
af2d4762a8 Merge pull request #250 from szimek/249_multiline_strings
Handle multiline strings in .env file
2012-09-14 01:34:10 -07:00
Aaron Kalin
1d06124457 Add StandardOutPath to launchd export 2012-09-11 15:04:15 -05:00
Aaron Kalin
698e6ae092 Add command argument string splitting
launchd uses exec() under the hood when you specify ProgramArguments
or Program so you must break apart program arguments into separate
strings in an array or the command will fail
2012-09-10 19:10:47 -05:00
Aaron Kalin
c617ddb3b2 Cleanup launchd exporter
Also suppresses the deprecation warning for the launchd exporter when
using port instead of engine.port_for
2012-09-10 18:21:51 -05:00
Aaron Kalin
f6d4badcd2 Enable trim_mode via '-' in ERB templates
This adds whitespace supression optionally, similar to the default
behavior in Rails ActionView ERB templates.

Just add - to a %> like so: -%> and it will remove trailing whitespace
and newlines. This can also be done to the beginning tag for removing
newlines from the beginning of the tag line.
2012-09-10 18:18:56 -05:00
Aaron Kalin
f29bf49a35 Add support for setting environment variables 2012-09-05 18:27:10 -05:00
David Dollar
e06d36b27c dont test 1.8.7 or rbx 2012-08-24 12:49:35 -04:00
David Dollar
85e62dfbeb Merge pull request #254 from omarkhan/master
foreman run should exit with the same code as its command
2012-08-24 09:14:45 -07:00
Omar Khan
574e852710 foreman run should exit with the same code as its command 2012-08-24 16:50:05 +01:00
David Dollar
68f098c1d2 update docs 2012-08-21 10:59:21 -04:00
David Dollar
e8bdafdfc1 changelog 2012-08-21 10:58:58 -04:00
Szymon Nowak
7d6de5b2a7 Handle multiline strings in .env file 2012-08-14 11:09:21 +02:00
Indrek Juhkam
8b204db2f0 Use path and env variables in the inittab export 2012-07-31 21:44:31 +03:00
Arnaud Lachaume
ebe160d425 fixed the directory option 2012-07-14 11:48:24 +10:00
Daniel Farrell
0a61b1a62f Add capistrano export support 2012-06-22 15:49:19 -04:00
41 changed files with 535 additions and 135 deletions

View File

@@ -16,9 +16,7 @@ notifications:
- http://dx-helper.herokuapp.com/travis
rvm:
- 1.8.7
- 1.9.2
- 1.9.3
- 2.0.0
- jruby
- rbx
- ree

View File

@@ -1,3 +1,65 @@
## 0.62.0 (2013-03-08)
* Merge pull request #334 from ged/reentrant_signal_handlers [David Dollar]
* Merge pull request #335 from ged/20_encoding_fix [David Dollar]
* Try to allow children to shut down gracefully [Michael Granger]
* Add deferred signal-handling (fixes #332). [Michael Granger]
* Fix spec encoding problem under Ruby 2.0.0. [Michael Granger]
* add ruby 2.0 to travis [David Dollar]
* Merge pull request #327 from patheticpat/master [David Dollar]
* Fixed a typo in cli options description [Michael Kaiser]
* handled by mingw now [David Dollar]
## 0.61.0 (2013-01-14)
* Fix bug in color definitons [nseo]
* Fix for high CPU load when processes close output [Pavel Forkert]
* Ensure foreman is the process group leader [Christos Trochalakis]
* Don't ignore blank lines in the output [Matt Venables]
* Add license to gemspec [petedmarsh]
* Since JRuby 1.9 doesn't require posix/spawn, only follow that path if JRuby is loaded and running in 1.8 mode. [Adam Hutchison]
* Remove explicit requirement on rubygems. [Cyril Rohr]
* Dont use shared_path variable before multistage has a chance at it [Aditya Sanghi]
* Strip Windows Line Endings [Paul Morton]
* Fix man page: --directory is actually --root. [Evan Jones]
* Add timeout switch to CLI [Paulo Luis Franchini Casaretto]
* Remove expectation of double quotes around environment variables from test comparisons [Kevin McAllister]
* Remove explicit wrapping of Shellwords.escape in double quotes [Kevin McAllister]
## 0.60.2 (2012-10-08)
* Fix for nil value on io select loop, fixes #260 [Silvio Relli]
## 0.60.1 (2012-10-08)
* sleep on select() to avoid spinning the cpu [Silvio Relli]
## 0.60.0 (2012-09-25)
* foreman run can run things from the Procfile like heroku run. [Dan Peterson]
## 0.59.0 (2012-09-15)
* Use /bin/sh instead of bash for foreman-runner [Jeremy Evans]
## 0.58.0 (2012-09-14)
* dont set HOME [David Dollar]
* Add StandardOutPath to launchd export [Aaron Kalin]
* Add command argument string splitting [Aaron Kalin]
* Cleanup launchd exporter [Aaron Kalin]
* Enable trim_mode via '-' in ERB templates [Aaron Kalin]
* Add support for setting environment variables [Aaron Kalin]
* foreman run should exit with the same code as its command [Omar Khan]
* Handle multiline strings in .env file [Szymon Nowak]
* Use path and env variables in the inittab export [Indrek Juhkam]
* fixed the directory option [Arnaud Lachaume]
* Add capistrano export support [Daniel Farrell]
## 0.57.0 (2012-08-21)
* fix startup checks for upstart exporter [Aditya Sanghi]
## 0.56.0 (2012-08-19)
* read .profile, not .profile.d [David Dollar]

View File

@@ -1,7 +1,8 @@
PATH
remote: .
specs:
foreman (0.57.0)
foreman (0.63.0)
dotenv (>= 0.7)
thor (>= 0.13.6)
GEM
@@ -13,6 +14,7 @@ GEM
xml-simple
builder (3.0.0)
diff-lcs (1.1.3)
dotenv (0.7.0)
fakefs (0.3.2)
hpricot (0.8.6)
hpricot (0.8.6-java)
@@ -39,7 +41,7 @@ GEM
multi_json (~> 1.0.3)
simplecov-html (~> 0.5.3)
simplecov-html (0.5.3)
thor (0.15.4)
thor (0.16.0)
timecop (0.3.5)
win32console (1.3.0-x86-mingw32)
xml-simple (1.0.15)

19
LICENSE Normal file
View File

@@ -0,0 +1,19 @@
Copyright (c) 2012 David Dollar
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -43,4 +43,6 @@ David Dollar
## License
MIT
Foreman is licensed under the MIT license.
See LICENSE for the full license text.

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/sh
#
#/ Usage: foreman-runner [-d <dir>] [-p] <command> [<args>...]
#/
@@ -32,9 +32,9 @@ shift $((OPTIND-1))
[ -z "$1" ] && usage
if [ "$read_profile" == "1" ]; then
if [ "$read_profile" = "1" ]; then
if [ -f .profile ]; then
source .profile
. ./.profile
fi
fi

View File

@@ -4,14 +4,25 @@
<dict>
<key>Label</key>
<string><%= "#{app}-#{name}-#{num}" %></string>
<key>EnvironmentVariables</key>
<dict>
<%- engine.env.merge("PORT" => port).each_pair do |var,env| -%>
<key><%= var.upcase %></key>
<string><%= env %></string>
<%- end -%>
</dict>
<key>ProgramArguments</key>
<array>
<string><%= process.command %></string>
<%- command_args.each do |command| -%>
<string><%= command %></string>
<%- end -%>
</array>
<key>KeepAlive</key>
<true/>
<key>RunAtLoad</key>
<true/>
<key>StandardOutPath</key>
<string><%= log %>/<%= app %>-<%= name %>-<%=num%>.log</string>
<key>StandardErrorPath</key>
<string><%= log %>/<%= app %>-<%= name %>-<%=num%>.log</string>
<key>UserName</key>

View File

@@ -7,10 +7,6 @@ EOF
end script
start on (started network-interface
or started network-manager
or started networking)
start on runlevel [2345]
stop on (stopping network-interface
or stopping network-manager
or stopping networking)
stop on runlevel [016]

16
dist/mswin32.rake vendored
View File

@@ -1,16 +0,0 @@
file pkg("foreman-#{version}-x86-mswin32.gem") => distribution_files do |t|
Bundler.with_clean_env do
sh "env PLATFORM=mswin32 gem build foreman.gemspec"
end
sh "mv foreman-#{version}-x86-mswin32.gem #{t.name}"
end
task "mswin32:build" => pkg("foreman-#{version}-x86-mswin32.gem")
task "mswin32:clean" do
clean pkg("foreman-#{version}-x86-mswin32.gem")
end
task "mswin32:release" => "mswin32:build" do |t|
sh "gem push #{pkg("foreman-#{version}-x86-mswin32.gem")} || echo 'error'"
end

View File

@@ -3,6 +3,7 @@ require "foreman/version"
Gem::Specification.new do |gem|
gem.name = "foreman"
gem.license = "MIT"
gem.version = Foreman::VERSION
gem.author = "David Dollar"
@@ -17,9 +18,9 @@ Gem::Specification.new do |gem|
gem.files << "man/foreman.1"
gem.add_dependency 'thor', '>= 0.13.6'
gem.add_dependency 'dotenv', '>= 0.7'
if ENV["PLATFORM"] == "java"
gem.add_dependency "posix-spawn", "~> 0.3.6"
gem.platform = Gem::Platform.new("java")
end

View File

@@ -8,8 +8,8 @@ module Foreman
File.expand_path("../../bin/foreman-runner", __FILE__)
end
def self.jruby?
defined?(RUBY_PLATFORM) and RUBY_PLATFORM == "java"
def self.jruby_18?
defined?(RUBY_PLATFORM) and RUBY_PLATFORM == "java" and ruby_18?
end
def self.ruby_18?

54
lib/foreman/capistrano.rb Normal file
View File

@@ -0,0 +1,54 @@
if defined?(Capistrano)
Capistrano::Configuration.instance(:must_exist).load do
namespace :foreman do
desc <<-DESC
Export the Procfile to upstart. Will use sudo if available.
You can override any of these defaults by setting the variables shown below.
set :foreman_format, "upstart"
set :foreman_location, "/etc/init"
set :foreman_procfile, "Procfile"
set :foreman_app, application
set :foreman_user, user
set :foreman_log, 'shared_path/log'
set :foreman_concurrency, false
DESC
task :export, :roles => :app do
bundle_cmd = fetch(:bundle_cmd, "bundle")
foreman_format = fetch(:foreman_format, "upstart")
foreman_location = fetch(:foreman_location, "/etc/init")
foreman_procfile = fetch(:foreman_procfile, "Procfile")
foreman_app = fetch(:foreman_app, application)
foreman_user = fetch(:foreman_user, user)
foreman_log = fetch(:foreman_log, "#{shared_path}/log")
foreman_concurrency = fetch(:foreman_concurrency, false)
args = ["#{foreman_format} #{foreman_location}"]
args << "-f #{foreman_procfile}"
args << "-a #{foreman_app}"
args << "-u #{foreman_user}"
args << "-l #{foreman_log}"
args << "-c #{foreman_concurrency}" if foreman_concurrency
run "cd #{release_path} && #{sudo} #{bundle_cmd} exec foreman export #{args.join(' ')}"
end
desc "Start the application services"
task :start, :roles => :app do
run "#{sudo} start #{application}"
end
desc "Stop the application services"
task :stop, :roles => :app do
run "#{sudo} stop #{application}"
end
desc "Restart the application services"
task :restart, :roles => :app do
run "#{sudo} start #{application} || #{sudo} restart #{application}"
end
end
end
end

View File

@@ -23,6 +23,7 @@ class Foreman::CLI < Thor
method_option :env, :type => :string, :aliases => "-e", :desc => "Specify an environment file to load, defaults to .env"
method_option :formation, :type => :string, :aliases => "-m", :banner => '"alpha=5,bar=3"'
method_option :port, :type => :numeric, :aliases => "-p"
method_option :timeout, :type => :numeric, :aliases => "-t", :desc => "Specify the amount of time (in seconds) processes have to shutdown gracefully before receiving a SIGKILL, defaults to 5."
class << self
# Hackery. Take the run method away from Thor so that we can redefine it.
@@ -75,10 +76,19 @@ class Foreman::CLI < Thor
def run(*args)
load_environment!
if File.exist?(procfile)
engine.load_procfile(procfile)
end
pid = fork do
begin
engine.env.each { |k,v| ENV[k] = v }
exec args.shelljoin
if args.size == 1 && process = engine.process(args.first)
process.exec(:env => engine.env)
else
exec args.shelljoin
end
rescue Errno::EACCES
error "not executable: #{args.first}"
rescue Errno::ENOENT
@@ -86,6 +96,7 @@ class Foreman::CLI < Thor
end
end
Process.wait(pid)
exit $?.exitstatus
end
desc "version", "Display Foreman gem version"
@@ -129,7 +140,7 @@ private ######################################################################
def procfile
case
when options[:procfile] then options[:procfile]
when options[:root] then File.expand_path(File.join(options[:app_root], "Procfile"))
when options[:root] then File.expand_path(File.join(options[:root], "Procfile"))
else "Procfile"
end
end

View File

@@ -1,7 +1,7 @@
require "foreman"
require "foreman/env"
require "foreman/process"
require "foreman/procfile"
require "dotenv"
require "tempfile"
require "timeout"
require "fileutils"
@@ -9,6 +9,10 @@ require "thread"
class Foreman::Engine
# The signals that the engine cares about.
#
HANDLED_SIGNALS = [ :TERM, :INT, :HUP ]
attr_reader :env
attr_reader :options
attr_reader :processes
@@ -25,6 +29,7 @@ class Foreman::Engine
@options = options.dup
@options[:formation] ||= (options[:concurrency] || "all=1")
@options[:timeout] ||= 5
@env = {}
@mutex = Mutex.new
@@ -32,15 +37,22 @@ class Foreman::Engine
@processes = []
@running = {}
@readers = {}
# Self-pipe for deferred signal-handling (ala djb: http://cr.yp.to/docs/selfpipe.html)
reader, writer = create_pipe
reader.close_on_exec = true if reader.respond_to?(:close_on_exec)
writer.close_on_exec = true if writer.respond_to?(:close_on_exec)
@selfpipe = { :reader => reader, :writer => writer }
# Set up a global signal queue
# http://blog.rubybestpractices.com/posts/ewong/016-Implementing-Signal-Handlers.html
Thread.main[:signal_queue] = []
end
# Start the processes registered to this +Engine+
#
def start
trap("TERM") { puts "SIGTERM received"; terminate_gracefully }
trap("INT") { puts "SIGINT received"; terminate_gracefully }
trap("HUP") { puts "SIGHUP received"; terminate_gracefully } if ::Signal.list.keys.include? 'HUP'
register_signal_handlers
startup
spawn_processes
watch_for_output
@@ -49,6 +61,74 @@ class Foreman::Engine
shutdown
end
# Set up deferred signal handlers
#
def register_signal_handlers
HANDLED_SIGNALS.each do |sig|
if ::Signal.list.include? sig.to_s
trap(sig) { Thread.main[:signal_queue] << sig ; notice_signal }
end
end
end
# Unregister deferred signal handlers
#
def restore_default_signal_handlers
HANDLED_SIGNALS.each do |sig|
trap(sig, :DEFAULT) if ::Signal.list.include? sig.to_s
end
end
# Wake the main thread up via the selfpipe when there's a signal
#
def notice_signal
@selfpipe[:writer].write_nonblock( '.' )
rescue Errno::EAGAIN
# Ignore writes that would block
rescue Errno::EINT
# Retry if another signal arrived while writing
retry
end
# Invoke the real handler for signal +sig+. This shouldn't be called directly
# by signal handlers, as it might invoke code which isn't re-entrant.
#
# @param [Symbol] sig the name of the signal to be handled
#
def handle_signal(sig)
case sig
when :TERM
handle_term_signal
when :INT
handle_interrupt
when :HUP
handle_hangup
else
system "unhandled signal #{sig}"
end
end
# Handle a TERM signal
#
def handle_term_signal
puts "SIGTERM received"
terminate_gracefully
end
# Handle an INT signal
#
def handle_interrupt
puts "SIGINT received"
terminate_gracefully
end
# Handle a HUP signal
#
def handle_hangup
puts "SIGHUP received"
terminate_gracefully
end
# Register a process to be run by this +Engine+
#
# @param [String] name A name for this process
@@ -89,16 +169,14 @@ class Foreman::Engine
# @param [String] filename A .env file to load into the environment
#
def load_env(filename)
Foreman::Env.new(filename).entries do |name, value|
@env[name] = value
end
@env.update Dotenv::Environment.new(filename)
end
# Send a signal to all processesstarted by this +Engine+
# Send a signal to all processes started by this +Engine+
#
# @param [String] signal The signal to send to each process
#
def killall(signal="SIGTERM")
def kill_children(signal="SIGTERM")
if Foreman.windows?
@running.each do |pid, (process, index)|
system "sending #{signal} to #{name_for(pid)} at pid #{pid}"
@@ -107,6 +185,21 @@ class Foreman::Engine
rescue Errno::ESRCH, Errno::EPERM
end
end
else
begin
Process.kill signal, *@running.keys unless @running.empty?
rescue Errno::ESRCH, Errno::EPERM
end
end
end
# Send a signal to the whole process group.
#
# @param [String] signal The signal to send
#
def killall(signal="SIGTERM")
if Foreman.windows?
kill_children(signal)
else
begin
Process.kill "-#{signal}", Process.pid
@@ -257,7 +350,6 @@ private
reader, writer = create_pipe
begin
pid = process.run(:output => writer, :env => {
"HOME" => process.cwd,
"PORT" => port_for(process, n).to_s
})
writer.puts "started with pid #{pid}"
@@ -274,9 +366,28 @@ private
Thread.new do
begin
loop do
(IO.select(@readers.values).first || []).each do |reader|
data = reader.gets
output_with_mutex name_for(@readers.invert[reader]), data
io = IO.select([@selfpipe[:reader]] + @readers.values, nil, nil, 30)
begin
@selfpipe[:reader].read_nonblock(11)
rescue Errno::EAGAIN, Errno::EINTR => err
# ignore
end
# Look for any signals that arrived and handle them
while sig = Thread.main[:signal_queue].shift
self.handle_signal(sig)
end
(io.nil? ? [] : io.first).each do |reader|
next if reader == @selfpipe[:reader]
if reader.eof?
@readers.delete_if { |key, value| value == reader }
else
data = reader.gets
output_with_mutex name_for(@readers.invert[reader]), data
end
end
end
rescue Exception => ex
@@ -297,15 +408,16 @@ private
def terminate_gracefully
return if @terminating
restore_default_signal_handlers
@terminating = true
if Foreman.windows?
system "sending SIGKILL to all processes"
killall "SIGKILL"
kill_children "SIGKILL"
else
system "sending SIGTERM to all processes"
killall "SIGTERM"
kill_children "SIGTERM"
end
Timeout.timeout(5) do
Timeout.timeout(options[:timeout]) do
watch_for_termination while @running.length > 0
end
rescue Timeout::Error

View File

@@ -44,8 +44,8 @@ class Foreman::Engine::CLI < Foreman::Engine
end
FOREMAN_COLORS = %w( cyan yellow green magenta red blue intense_cyan intense_yellow
intense_green intense_magenta intense_red, intense_blue )
FOREMAN_COLORS = %w( cyan yellow green magenta red blue bright_cyan bright_yellow
bright_green bright_magenta bright_red bright_blue )
def startup
@colors = map_colors
@@ -54,7 +54,7 @@ class Foreman::Engine::CLI < Foreman::Engine
end
def output(name, data)
data.to_s.chomp.split("\n").each do |message|
data.to_s.lines.map(&:chomp).each do |message|
output = ""
output += $stdout.color(@colors[name.split(".").first].to_sym)
output += "#{Time.now.strftime("%H:%M:%S")} #{pad_process_name(name)} | "
@@ -89,7 +89,7 @@ private
@names.values.each_with_index do |name, index|
colors[name] = FOREMAN_COLORS[index % FOREMAN_COLORS.length]
end
colors["system"] = "intense_white"
colors["system"] = "bright_white"
colors
end

View File

@@ -1,27 +0,0 @@
require "foreman"
class Foreman::Env
attr_reader :entries
def initialize(filename)
@entries = File.read(filename).split("\n").inject({}) do |ax, line|
if line =~ /\A([A-Za-z_0-9]+)=(.*)\z/
key = $1
case val = $2
when /\A'(.*)'\z/ then ax[key] = $1
when /\A"(.*)"\z/ then ax[key] = $1.gsub(/\\(.)/, '\1')
else ax[key] = val
end
end
ax
end
end
def entries
@entries.each do |key, value|
yield key, value
end
end
end

View File

@@ -91,7 +91,7 @@ private ######################################################################
end
def shell_quote(value)
'"' + Shellwords.escape(value) + '"'
Shellwords.escape(value)
end
# deprecated
@@ -119,7 +119,7 @@ private ######################################################################
end
def write_template(name, target, binding)
compiled = ERB.new(export_template(name)).result(binding)
compiled = ERB.new(export_template(name), nil, '-').result(binding)
write_file target, compiled
end

View File

@@ -13,7 +13,16 @@ class Foreman::Export::Inittab < Foreman::Export::Base
1.upto(engine.formation[name]) do |num|
id = app.slice(0, 2).upcase + sprintf("%02d", index)
port = engine.port_for(process, num)
inittab << "#{id}:4:respawn:/bin/su - #{user} -c 'PORT=#{port} #{process.command} >> #{log}/#{name}-#{num}.log 2>&1'"
commands = []
commands << "cd #{engine.root}"
commands << "export PORT=#{port}"
engine.env.each_pair do |var, env|
commands << "export #{var.upcase}=#{shell_quote(env)}"
end
commands << "#{process.command} >> #{log}/#{name}-#{num}.log 2>&1"
inittab << "#{id}:4:respawn:/bin/su - #{user} -c '#{commands.join(";")}'"
index += 1
end
end

View File

@@ -7,6 +7,8 @@ class Foreman::Export::Launchd < Foreman::Export::Base
super
engine.each_process do |name, process|
1.upto(engine.formation[name]) do |num|
port = engine.port_for(process, num)
command_args = process.command.split(" ")
write_template "launchd/launchd.plist.erb", "#{app}-#{name}-#{num}.plist", binding
end
end

View File

@@ -6,7 +6,7 @@ class Foreman::Export::Upstart < Foreman::Export::Base
def export
super
Dir["#{location}/#{app}*.conf"].each do |file|
(Dir["#{location}/#{app}-*.conf"] << "#{location}/#{app}.conf").each do |file|
clean file
end

View File

@@ -1,5 +1,4 @@
require "foreman"
require "rubygems"
class Foreman::Process
@@ -21,6 +20,21 @@ class Foreman::Process
@options[:env] ||= {}
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
@@ -31,18 +45,14 @@ class Foreman::Process
# @returns [Fixnum] pid The +pid+ of the process
#
def run(options={})
env = options[:env] ? @options[:env].merge(options[:env]) : @options[:env]
env = @options[:env].merge(options[:env] || {})
output = options[:output] || $stdout
if Foreman.windows?
Dir.chdir(cwd) do
expanded_command = command.dup
env.each do |key, val|
expanded_command.gsub!("$#{key}", val)
end
Process.spawn env, expanded_command, :out => output, :err => output
Process.spawn env, expanded_command(env), :out => output, :err => output
end
elsif Foreman.jruby?
elsif Foreman.jruby_18?
require "posix/spawn"
wrapped_command = "#{Foreman.runner} -d '#{cwd}' -p -- #{command}"
POSIX::Spawn.spawn env, wrapped_command, :out => output, :err => output
@@ -52,7 +62,7 @@ class Foreman::Process
$stderr.reopen output
env.each { |k,v| ENV[k] = v }
wrapped_command = "#{Foreman.runner} -d '#{cwd}' -p -- #{command}"
exec wrapped_command
Kernel.exec wrapped_command
end
else
wrapped_command = "#{Foreman.runner} -d '#{cwd}' -p -- #{command}"
@@ -60,6 +70,20 @@ class Foreman::Process
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

View File

@@ -82,8 +82,8 @@ class Foreman::Procfile
private
def parse(filename)
File.read(filename).split("\n").map do |line|
if line =~ /^([A-Za-z0-9_]+):\s*(.+)$/
File.read(filename).gsub("\r\n","\n").split("\n").map do |line|
if line =~ /^([A-Za-z0-9_-]+):\s*(.+)$/
[$1, $2]
end
end.compact

View File

@@ -1,5 +1,5 @@
module Foreman
VERSION = "0.57.0"
VERSION = "0.63.0"
end

View File

@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "FOREMAN" "1" "July 2012" "Foreman 0.51.0" "Foreman Manual"
.TH "FOREMAN" "1" "January 2013" "Foreman 0.61.0" "Foreman Manual"
.
.SH "NAME"
\fBforeman\fR \- manage Procfile\-based applications
@@ -46,10 +46,6 @@ Specify an alternate Procfile to load, implies \fB\-d\fR at the Procfile root\.
\fB\-p\fR, \fB\-\-port\fR
Specify which port to use as the base for this application\. Should be a multiple of 1000\.
.
.TP
\fB\-t\fR, \fB\-\-tmux\fR
Runs the processes in a tmux session\. Creates one window for each process and an extra window containing the output of each window (requires gawk)\.
.
.P
\fBforeman run\fR is used to run one\-off commands using the same environment as your defined processes\.
.
@@ -90,7 +86,7 @@ Specify the user the application should be run as\. Defaults to the app name
These options control all modes of foreman\'s operation\.
.
.TP
\fB\-d\fR, \fB\-\-directory\fR
\fB\-d\fR, \fB\-\-root\fR
Specify an alternate application root\. This defaults to the directory containing the Procfile\.
.
.TP
@@ -234,7 +230,7 @@ Run one process type from the application defined in a specific Procfile:
.
.nf
$ foreman start alpha \-p ~/myapp/Procfile
$ foreman start alpha \-f ~/myapp/Procfile
.
.fi
.

View File

@@ -40,10 +40,6 @@ The following options control how the application is run:
Specify which port to use as the base for this application. Should be
a multiple of 1000.
* `-t`, `--tmux`:
Runs the processes in a tmux session. Creates one window for each process
and an extra window containing the output of each window (requires gawk).
`foreman run` is used to run one-off commands using the same environment
as your defined processes.
@@ -84,7 +80,7 @@ The following options control how the application is run:
These options control all modes of foreman's operation.
* `-d`, `--directory`:
* `-d`, `--root`:
Specify an alternate application root. This defaults to the directory
containing the Procfile.

View File

@@ -50,7 +50,7 @@ describe "Foreman::CLI", :fakefs do
describe "check" do
it "with a valid Procfile displays the jobs" do
write_procfile
foreman("check").should == "valid procfile detected (alpha, bravo)\n"
foreman("check").should == "valid procfile detected (alpha, bravo, foo_bar, foo-bar)\n"
end
it "with a blank Procfile displays an error" do
@@ -72,6 +72,15 @@ describe "Foreman::CLI", :fakefs do
it "includes the environment" do
forked_foreman("run #{resource_path("bin/env FOO")} -e #{resource_path(".env")}").should == "bar\n"
end
it "can run a command from the Procfile" do
forked_foreman("run -f #{resource_path("Procfile")} test").should == "testing\n"
end
it "exits with the same exit code as the command" do
fork_and_get_exitstatus("run echo 1").should == 0
fork_and_get_exitstatus("run date 'invalid_date'").should == 1
end
end
describe "version" do

View File

@@ -90,6 +90,14 @@ describe "Foreman::Engine", :fakefs do
subject.env["OTHER"].should == 'escaped"quote'
end
it "should handle multiline strings" do
File.open("/tmp/env", "w") do |f|
f.puts 'FOO="bar\nbaz"'
end
subject.load_env "/tmp/env"
subject.env["FOO"].should == "bar\nbaz"
end
it "should fail if specified and doesnt exist" do
lambda { subject.load_env "/tmp/env" }.should raise_error(Errno::ENOENT)
end

View File

@@ -18,4 +18,14 @@ describe Foreman::Export::Launchd, :fakefs do
File.read("/tmp/init/app-bravo-1.plist").should == example_export_file("launchd/launchd-b.default")
end
context "with multiple command arguments" do
let(:procfile) { FileUtils.mkdir_p("/tmp/app"); write_procfile("/tmp/app/Procfile", "charlie") }
it "splits each command argument" do
launchd.export
File.read("/tmp/init/app-alpha-1.plist").should == example_export_file("launchd/launchd-c.default")
end
end
end

View File

@@ -29,16 +29,32 @@ describe Foreman::Export::Upstart, :fakefs do
mock(FileUtils).rm("/tmp/init/app-alpha-1.conf")
mock(FileUtils).rm("/tmp/init/app-bravo.conf")
mock(FileUtils).rm("/tmp/init/app-bravo-1.conf")
mock(FileUtils).rm("/tmp/init/app-foo-bar.conf")
mock(FileUtils).rm("/tmp/init/app-foo-bar-1.conf")
mock(FileUtils).rm("/tmp/init/app-foo_bar.conf")
mock(FileUtils).rm("/tmp/init/app-foo_bar-1.conf")
upstart.export
upstart.export
end
it "does not delete exported files for similarly named applications" do
FileUtils.mkdir_p "/tmp/init"
["app2", "app2-alpha", "app2-alpha-1"].each do |name|
path = "/tmp/init/#{name}.conf"
FileUtils.touch(path)
dont_allow(FileUtils).rm(path)
end
upstart.export
end
it "quotes and escapes environment variables" do
engine.env['KEY'] = 'd"\|d'
upstart.export
"foobarfoo".should include "bar"
File.read("/tmp/init/app-alpha-1.conf").should =~ /KEY="d\\"\\\\\\\|d/
File.read("/tmp/init/app-alpha-1.conf").should =~ /KEY=d\\"\\\\\\\|d/
end
context "with a formation" do

View File

@@ -41,7 +41,7 @@ describe Foreman::Process do
it "should output utf8 properly" do
process = Foreman::Process.new(resource_path("bin/utf8"))
run(process).should == "\xFF\x03\n"
run(process).should == "\xFF\x03\n".force_encoding('binary')
end
end

View File

@@ -16,8 +16,10 @@ describe Foreman::Procfile, :fakefs do
it "loads a passed-in Procfile" do
write_procfile
procfile = Foreman::Procfile.new("Procfile")
procfile["alpha"].should == "./alpha"
procfile["bravo"].should == "./bravo"
procfile["alpha"].should == "./alpha"
procfile["bravo"].should == "./bravo"
procfile["foo-bar"].should == "./foo-bar"
procfile["foo_bar"].should == "./foo_bar"
end
it "can have a process appended to it" do

View File

@@ -42,5 +42,40 @@ Bluepill.application("app", :foreground => false, :log_file => "/var/log/bluepil
process.group = "app-bravo"
end
app.process("foo_bar-1") do |process|
process.start_command = "./foo_bar"
process.working_dir = "/tmp/app"
process.daemonize = true
process.environment = {"PORT"=>"5200"}
process.stop_signals = [:quit, 30.seconds, :term, 5.seconds, :kill]
process.stop_grace_time = 45.seconds
process.stdout = process.stderr = "/var/log/app/app-foo_bar-1.log"
process.monitor_children do |children|
children.stop_command "kill {{PID}}"
end
process.group = "app-foo_bar"
end
app.process("foo-bar-1") do |process|
process.start_command = "./foo-bar"
process.working_dir = "/tmp/app"
process.daemonize = true
process.environment = {"PORT"=>"5300"}
process.stop_signals = [:quit, 30.seconds, :term, 5.seconds, :kill]
process.stop_grace_time = 45.seconds
process.stdout = process.stderr = "/var/log/app/app-foo-bar-1.log"
process.monitor_children do |children|
children.stop_command "kill {{PID}}"
end
process.group = "app-foo-bar"
end
end

View File

@@ -1,4 +1,4 @@
# ----- foreman app processes -----
AP01:4:respawn:/bin/su - app -c 'PORT=5000 ./alpha >> /var/log/app/alpha-1.log 2>&1'
AP02:4:respawn:/bin/su - app -c 'PORT=5001 ./alpha >> /var/log/app/alpha-2.log 2>&1'
AP01:4:respawn:/bin/su - app -c 'cd /tmp/app;export PORT=5000;./alpha >> /var/log/app/alpha-1.log 2>&1'
AP02:4:respawn:/bin/su - app -c 'cd /tmp/app;export PORT=5001;./alpha >> /var/log/app/alpha-2.log 2>&1'
# ----- end foreman app processes -----

View File

@@ -1,4 +1,6 @@
# ----- foreman app processes -----
AP01:4:respawn:/bin/su - app -c 'PORT=5000 ./alpha >> /var/log/app/alpha-1.log 2>&1'
AP02:4:respawn:/bin/su - app -c 'PORT=5100 ./bravo >> /var/log/app/bravo-1.log 2>&1'
AP01:4:respawn:/bin/su - app -c 'cd /tmp/app;export PORT=5000;./alpha >> /var/log/app/alpha-1.log 2>&1'
AP02:4:respawn:/bin/su - app -c 'cd /tmp/app;export PORT=5100;./bravo >> /var/log/app/bravo-1.log 2>&1'
AP03:4:respawn:/bin/su - app -c 'cd /tmp/app;export PORT=5200;./foo_bar >> /var/log/app/foo_bar-1.log 2>&1'
AP04:4:respawn:/bin/su - app -c 'cd /tmp/app;export PORT=5300;./foo-bar >> /var/log/app/foo-bar-1.log 2>&1'
# ----- end foreman app processes -----

View File

@@ -4,6 +4,11 @@
<dict>
<key>Label</key>
<string>app-alpha-1</string>
<key>EnvironmentVariables</key>
<dict>
<key>PORT</key>
<string>5000</string>
</dict>
<key>ProgramArguments</key>
<array>
<string>./alpha</string>
@@ -12,6 +17,8 @@
<true/>
<key>RunAtLoad</key>
<true/>
<key>StandardOutPath</key>
<string>/var/log/app/app-alpha-1.log</string>
<key>StandardErrorPath</key>
<string>/var/log/app/app-alpha-1.log</string>
<key>UserName</key>

View File

@@ -4,6 +4,11 @@
<dict>
<key>Label</key>
<string>app-bravo-1</string>
<key>EnvironmentVariables</key>
<dict>
<key>PORT</key>
<string>5100</string>
</dict>
<key>ProgramArguments</key>
<array>
<string>./bravo</string>
@@ -12,6 +17,8 @@
<true/>
<key>RunAtLoad</key>
<true/>
<key>StandardOutPath</key>
<string>/var/log/app/app-bravo-1.log</string>
<key>StandardErrorPath</key>
<string>/var/log/app/app-bravo-1.log</string>
<key>UserName</key>

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>app-alpha-1</string>
<key>EnvironmentVariables</key>
<dict>
<key>PORT</key>
<string>5000</string>
</dict>
<key>ProgramArguments</key>
<array>
<string>./alpha</string>
<string>charlie</string>
</array>
<key>KeepAlive</key>
<true/>
<key>RunAtLoad</key>
<true/>
<key>StandardOutPath</key>
<string>/var/log/app/app-alpha-1.log</string>
<key>StandardErrorPath</key>
<string>/var/log/app/app-alpha-1.log</string>
<key>UserName</key>
<string>app</string>
<key>WorkingDirectory</key>
<string>/tmp/app</string>
</dict>
</plist>

View File

@@ -8,7 +8,7 @@ stdout_logfile=/var/log/app/alpha-1.log
stderr_logfile=/var/log/app/alpha-1.error.log
user=app
directory=/tmp/app
environment=PORT="5000"
environment=PORT=5000
[program:app-bravo-1]
command=./bravo
autostart=true
@@ -18,7 +18,27 @@ stdout_logfile=/var/log/app/bravo-1.log
stderr_logfile=/var/log/app/bravo-1.error.log
user=app
directory=/tmp/app
environment=PORT="5100"
environment=PORT=5100
[program:app-foo_bar-1]
command=./foo_bar
autostart=true
autorestart=true
stopsignal=QUIT
stdout_logfile=/var/log/app/foo_bar-1.log
stderr_logfile=/var/log/app/foo_bar-1.error.log
user=app
directory=/tmp/app
environment=PORT=5200
[program:app-foo-bar-1]
command=./foo-bar
autostart=true
autorestart=true
stopsignal=QUIT
stdout_logfile=/var/log/app/foo-bar-1.log
stderr_logfile=/var/log/app/foo-bar-1.error.log
user=app
directory=/tmp/app
environment=PORT=5300
[group:app]
programs=app-alpha-1,app-bravo-1
programs=app-alpha-1,app-bravo-1,app-foo_bar-1,app-foo-bar-1

View File

@@ -8,7 +8,7 @@ stdout_logfile=/var/log/app/alpha-1.log
stderr_logfile=/var/log/app/alpha-1.error.log
user=app
directory=/tmp/app
environment=PORT="5000"
environment=PORT=5000
[program:app-alpha-2]
command=./alpha
autostart=true
@@ -18,7 +18,7 @@ stdout_logfile=/var/log/app/alpha-2.log
stderr_logfile=/var/log/app/alpha-2.error.log
user=app
directory=/tmp/app
environment=PORT="5001"
environment=PORT=5001
[group:app]
programs=app-alpha-1,app-alpha-2

View File

@@ -7,10 +7,6 @@ EOF
end script
start on (started network-interface
or started network-manager
or started networking)
start on runlevel [2345]
stop on (stopping network-interface
or stopping network-manager
or stopping networking)
stop on runlevel [016]

View File

@@ -1,5 +1,3 @@
require "rubygems"
require "simplecov"
SimpleCov.start do
add_filter "/spec/"
@@ -58,6 +56,12 @@ def fork_and_capture(&blk)
end
end
def fork_and_get_exitstatus(args)
pid = Process.spawn("bundle exec bin/foreman #{args}", :out => "/dev/null", :err => "/dev/null")
Process.wait(pid)
$?.exitstatus
end
def mock_exit(&block)
block.should raise_error(SystemExit)
end
@@ -75,6 +79,8 @@ def write_procfile(procfile="Procfile", alpha_env="")
file.puts "alpha: ./alpha" + " #{alpha_env}".rstrip
file.puts "\n"
file.puts "bravo:\t./bravo"
file.puts "foo_bar:\t./foo_bar"
file.puts "foo-bar:\t./foo-bar"
end
File.expand_path(procfile)
end