activerain-mongrel_runit 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/CHANGELOG.txt +8 -0
  2. data/History.txt +0 -0
  3. data/LICENSE +339 -0
  4. data/Manifest.txt +11 -0
  5. data/README.txt +123 -0
  6. data/Rakefile +58 -0
  7. data/bin/mongrel_runit +9 -0
  8. data/lib/mongrel_runit.rb +25 -0
  9. data/lib/mongrel_runit/base.rb +58 -0
  10. data/lib/mongrel_runit/cli.rb +60 -0
  11. data/lib/mongrel_runit/config.rb +184 -0
  12. data/lib/mongrel_runit/service.rb +253 -0
  13. data/lib/mongrel_runit/servicerunner.rb +91 -0
  14. data/lib/mongrel_runit/version.rb +9 -0
  15. data/test/config/mongrel_runit.yml +21 -0
  16. data/test/config/mongrel_runit_service.yml +12 -0
  17. data/test/tc_config.rb +93 -0
  18. data/test/tc_service.rb +153 -0
  19. data/test/tc_servicerunner.rb +74 -0
  20. data/test/test_helper.rb +2 -0
  21. data/test/test_mongrel_runit.rb +9 -0
  22. data/test/testapp/README +182 -0
  23. data/test/testapp/Rakefile +10 -0
  24. data/test/testapp/app/controllers/application.rb +7 -0
  25. data/test/testapp/app/helpers/application_helper.rb +3 -0
  26. data/test/testapp/config/boot.rb +45 -0
  27. data/test/testapp/config/database.yml +36 -0
  28. data/test/testapp/config/environment.rb +60 -0
  29. data/test/testapp/config/environments/development.rb +21 -0
  30. data/test/testapp/config/environments/production.rb +18 -0
  31. data/test/testapp/config/environments/test.rb +19 -0
  32. data/test/testapp/config/routes.rb +23 -0
  33. data/test/testapp/doc/README_FOR_APP +2 -0
  34. data/test/testapp/log/development.log +0 -0
  35. data/test/testapp/log/production.log +3010 -0
  36. data/test/testapp/log/server.log +0 -0
  37. data/test/testapp/log/test.log +0 -0
  38. data/test/testapp/public/404.html +30 -0
  39. data/test/testapp/public/500.html +30 -0
  40. data/test/testapp/public/dispatch.cgi +10 -0
  41. data/test/testapp/public/dispatch.fcgi +24 -0
  42. data/test/testapp/public/dispatch.rb +10 -0
  43. data/test/testapp/public/favicon.ico +0 -0
  44. data/test/testapp/public/images/rails.png +0 -0
  45. data/test/testapp/public/index.html +277 -0
  46. data/test/testapp/public/javascripts/application.js +2 -0
  47. data/test/testapp/public/javascripts/controls.js +833 -0
  48. data/test/testapp/public/javascripts/dragdrop.js +942 -0
  49. data/test/testapp/public/javascripts/effects.js +1088 -0
  50. data/test/testapp/public/javascripts/prototype.js +2515 -0
  51. data/test/testapp/public/robots.txt +1 -0
  52. data/test/testapp/script/about +3 -0
  53. data/test/testapp/script/breakpointer +3 -0
  54. data/test/testapp/script/console +3 -0
  55. data/test/testapp/script/destroy +3 -0
  56. data/test/testapp/script/generate +3 -0
  57. data/test/testapp/script/performance/benchmarker +3 -0
  58. data/test/testapp/script/performance/profiler +3 -0
  59. data/test/testapp/script/plugin +3 -0
  60. data/test/testapp/script/process/inspector +3 -0
  61. data/test/testapp/script/process/reaper +3 -0
  62. data/test/testapp/script/process/spawner +3 -0
  63. data/test/testapp/script/runner +3 -0
  64. data/test/testapp/script/server +3 -0
  65. data/test/testapp/test/test_helper.rb +28 -0
  66. metadata +157 -0
@@ -0,0 +1,58 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rake/testtask'
5
+ require 'rake/packagetask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/rdoctask'
8
+ require 'rake/contrib/rubyforgepublisher'
9
+ require 'fileutils'
10
+ require 'hoe'
11
+ require "delegate"
12
+ include FileUtils
13
+ require File.join(File.dirname(__FILE__), 'lib', 'mongrel_runit', 'version')
14
+
15
+ AUTHOR = "Adam Jacob" # can also be an array of Authors
16
+ EMAIL = "adam@hjksolutions.com"
17
+ DESCRIPTION = "Use runit to manage a mongrel cluster"
18
+ GEM_NAME = "mongrel_runit" # what ppl will type to install your gem
19
+ RUBYFORGE_PROJECT = "mongrel_runit" # The unix name for your project
20
+ HOMEPATH = "https://wiki.hjksolutions.com/display/MR/Home"
21
+
22
+ NAME = "mongrel_runit"
23
+ REV = nil # UNCOMMENT IF REQUIRED: File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil
24
+ VERS = ENV['VERSION'] || (MongrelRunit::VERSION::STRING + (REV ? ".#{REV}" : ""))
25
+ CLEAN.include ['**/.*.sw?', '*.gem', '.config']
26
+ RDOC_OPTS = ['--quiet', '--title', "mongrel_runit documentation",
27
+ "--opname", "index.html",
28
+ "--line-numbers",
29
+ "--main", "README",
30
+ "--inline-source"]
31
+
32
+ class Hoe
33
+ def extra_deps
34
+ @extra_deps.reject { |x| Array(x).first == 'hoe' }
35
+ end
36
+ end
37
+
38
+ # Generate all the Rake tasks
39
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
40
+ hoe = Hoe.new(GEM_NAME, VERS) do |p|
41
+ p.author = AUTHOR
42
+ p.description = DESCRIPTION
43
+ p.email = EMAIL
44
+ p.summary = DESCRIPTION
45
+ p.url = HOMEPATH
46
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
47
+ p.test_globs = ["test/**/*_test.rb"]
48
+ p.clean_globs = CLEAN #An array of file patterns to delete on clean.
49
+
50
+ # == Optional
51
+ #p.changes - A description of the release's latest changes.
52
+ #p.extra_deps - An array of rubygem dependencies.
53
+ p.spec_extras = {
54
+ "files" => FileList['lib/**/*.rb', 'bin/*', '[A-Z]*', 'test/**/*'].to_a,
55
+ "executables" => [ "mongrel_runit" ],
56
+ } # - A hash of extra values to set in the gemspec.
57
+ end
58
+
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Created by Adam Jacob on 2007-03-22.
4
+ # Copyright (c) 2007. All rights reserved.
5
+
6
+ require 'mongrel_runit/cli'
7
+
8
+ cli = MongrelRunit::CLI.new(ARGV)
9
+ cli.execute
@@ -0,0 +1,25 @@
1
+ #
2
+ # Mongrel Runit takes a yaml config file and automatically sets up a
3
+ # group of mongrels for you. It is functionally equivilant to
4
+ # mongrel_cluster, but relies on runit for the fairly complex daemon
5
+ # management tasks.
6
+ #
7
+ # Author:: Adam Jacob (<adam@hjksolutions.com>)
8
+ # Copyright:: Copyright (c) 2007 HJK Solutions, LLC
9
+ # License:: GNU General Public License version 2.1
10
+ #
11
+ # This program is free software; you can redistribute it and/or modify
12
+ # it under the terms of the GNU General Public License version 2
13
+ # as published by the Free Software Foundation.
14
+ #
15
+ # This program is distributed in the hope that it will be useful,
16
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
+ # GNU General Public License for more details.
19
+ #
20
+ # You should have received a copy of the GNU General Public License along
21
+ # with this program; if not, write to the Free Software Foundation, Inc.,
22
+ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23
+
24
+
25
+ Dir[File.join(File.dirname(__FILE__), 'mongrel_runit/**/*.rb')].sort.each { |lib| require lib }
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Author:: Adam Jacob (<adam@hjksolutions.com>)
4
+ # Copyright:: Copyright (c) 2007 HJK Solutions, LLC
5
+ # License:: GNU General Public License version 2
6
+ #---
7
+ # This program is free software; you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License version 2
9
+ # as published by the Free Software Foundation.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License along
17
+ # with this program; if not, write to the Free Software Foundation, Inc.,
18
+ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
+ #+++
20
+
21
+
22
+ module MongrelRunit
23
+
24
+ # A simple base class, that defines a list of allowed commands.
25
+ class Base
26
+ ALLOWEDCOMMANDS = [
27
+ "up",
28
+ "down",
29
+ "status",
30
+ "once",
31
+ "pause",
32
+ "cont",
33
+ "hup",
34
+ "alarm",
35
+ "interrupt",
36
+ "1",
37
+ "2",
38
+ "term",
39
+ "kill",
40
+ "exit",
41
+ "start",
42
+ "stop",
43
+ "restart",
44
+ "shut-down",
45
+ "force-stop",
46
+ "force-reload",
47
+ "force-restart",
48
+ "force-shutdown",
49
+ ]
50
+
51
+ # Returns a given command if it's found in the allowed commands
52
+ # list.
53
+ def has_command?(command)
54
+ ALLOWEDCOMMANDS.detect { |cmd| cmd == command }
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Author:: Adam Jacob (<adam@hjksolutions.com>)
4
+ # Copyright:: Copyright (c) 2007 HJK Solutions, LLC
5
+ # License:: GNU General Public License version 2
6
+ #
7
+ #--
8
+ # This program is free software; you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License version 2
10
+ # as published by the Free Software Foundation.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License along
18
+ # with this program; if not, write to the Free Software Foundation, Inc.,
19
+ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
+ #++
21
+
22
+ require 'optparse'
23
+ require 'mongrel_runit/servicerunner'
24
+ require 'mongrel_runit/config'
25
+ require 'yaml'
26
+
27
+ module MongrelRunit
28
+
29
+ # The command line interface.
30
+ #
31
+ # Example:
32
+ #
33
+ # cli = MongrelRunit::CLI.new(ARGV)
34
+ # cli.execute
35
+ #
36
+
37
+ class CLI
38
+
39
+ # Takes a list of command line arguments, passing them to
40
+ # MongrelRunit::Config and MongrelRunit::ServiceRunner.
41
+ def initialize(args)
42
+ @config = MongrelRunit::Config.load_args(args)
43
+ @servicerunner = MongrelRunit::ServiceRunner.new(@config.config)
44
+ end
45
+
46
+ # Executes the command (start/stop/restart; see MongrelRunit::Base for the
47
+ # list) specified by the arguments passed to MongrelRunit::CLI. The
48
+ # command is executed by calling MongrelRunit::ServiceRunner.run.
49
+ def execute
50
+ response, status = @servicerunner.run(@config.command)
51
+ if @config.verbose || status == false
52
+ response.sort.each do |key, value|
53
+ puts "#{key}: #{value[1]}: #{value[0]}"
54
+ end
55
+ end
56
+ exit 1 if status == false
57
+ exit 0 if status == true
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,184 @@
1
+ # Author:: Adam Jacob (<adam@hjksolutions.com>)
2
+ # Copyright:: Copyright (c) 2007 HJK Solutions, LLC
3
+ # License:: GNU General Public License version 2
4
+ #---
5
+ # This program is free software; you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License version 2
7
+ # as published by the Free Software Foundation.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License along
15
+ # with this program; if not, write to the Free Software Foundation, Inc.,
16
+ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
+ #+++
18
+
19
+ require 'yaml'
20
+ require 'optparse'
21
+ require 'mongrel_runit/base'
22
+
23
+ module MongrelRunit
24
+
25
+ # Takes a YAML config file and a list of command line arguments, and
26
+ # populates itself with the resulting combined configuration.
27
+ #
28
+ # Example:
29
+ #
30
+ # config = MongrelRunit::Config('monkey', '/etc/sv/monkey.yml', ARGV)
31
+ # puts config["application_name"] # monkey
32
+ #
33
+ class Config < Base
34
+ attr_accessor :config, :command, :verbose
35
+
36
+ # Takes an application name, a YAML file, and command line arguments
37
+ # and spits out a working configuration. The YAML file and arguments
38
+ # can optionally be nil.
39
+ #
40
+ # Unless otherwise specified, the following default values are
41
+ # set:
42
+ #
43
+ # environment: ENV["RAILS_ENV"] or development
44
+ # port: 3000
45
+ # servers: 2
46
+ # runit_svdir: /etc/sv
47
+ # runit_service_dir: /var/service
48
+ def initialize(appname, yamlfile, args)
49
+ @config = Hash.new
50
+ load_args(args) if args
51
+ load_yaml(yamlfile) if yamlfile
52
+ @config["environment"] ||= ENV["RAILS_ENV"] || 'development'
53
+ @config["port"] ||= "3000"
54
+ @config["servers"] ||= 2
55
+ @config["application_name"] ||= appname
56
+ @config["runit_svdir"] ||= '/etc/sv'
57
+ @config["runit_service_dir"] ||= '/var/service'
58
+ @config["address"] ||= '127.0.0.1'
59
+
60
+ raise ArgumentError, "Must supply an application_name!" unless @config["application_name"]
61
+
62
+ end
63
+
64
+ # Returns the value from the config hash.
65
+ def [](arg)
66
+ @config[arg]
67
+ end
68
+
69
+ # Load options from a config file alone
70
+ def Config.load_file(yamlfile)
71
+ MongrelRunit::Config.new(nil, yamlfile, nil)
72
+ end
73
+
74
+ # Load options from command line arguments alone
75
+ def Config.load_args(*args)
76
+ MongrelRunit::Config.new(nil, nil, *args)
77
+ end
78
+
79
+ private
80
+
81
+ def load_yaml(yamlfile)
82
+ @config = YAML.load_file(File.expand_path(yamlfile))
83
+ end
84
+
85
+ def load_from_path(path)
86
+ path.strip!
87
+ epath = File.expand_path(path)
88
+ @path = epath
89
+ mr_conf = File.expand_path(File.join(epath, "config", "mongrel_runit.yml"))
90
+ mc_conf = File.expand_path(File.join(epath, "config", "mongrel_cluster.yml"))
91
+ if File.file?(mr_conf)
92
+ load_yaml(mr_conf)
93
+ elsif File.file?(mc_conf)
94
+ load_yaml(mc_conf)
95
+ else
96
+ puts "#{path} must have a ./config/mongrel_runit.yml or ./config/mongrel_cluster.yml"
97
+ return nil
98
+ end
99
+ return true
100
+ end
101
+
102
+ def load_args(args)
103
+
104
+ loaded_config = nil
105
+
106
+ opts = OptionParser.new do |opts|
107
+ opts.banner = "Usage: #{$0} (options) (#{ALLOWEDCOMMANDS.join('|')})"
108
+
109
+ opts.on("-p PATH", "--path PATH", "Path to a Rails app to start") do |p|
110
+ loaded_config = load_from_path(p)
111
+ end
112
+
113
+ opts.on("-a NAME", "--application NAME", "The name of your Application. (Used for the service directories)") do |a|
114
+ @config["application_name"] = a
115
+ end
116
+
117
+ opts.on("-c FILE", "--config FILE", "A mongrel_runit.yml config file") do |c|
118
+ c.strip!
119
+ file = File.expand_path(c)
120
+ if File.file?(file)
121
+ load_yaml(file)
122
+ loaded_config = true
123
+ else
124
+ puts "I could not find config file: #{file}"
125
+ exit 1
126
+ end
127
+ end
128
+
129
+ opts.on_tail("-v", "--verbose", "Be verbose") do
130
+ @verbose = true
131
+ end
132
+
133
+ opts.on_tail("-h", "--help", "Show this message") do
134
+ puts opts
135
+ exit
136
+ end
137
+ end
138
+ opts.parse!(args)
139
+
140
+ unless loaded_config
141
+ path = Dir.getwd
142
+ loaded_config = load_from_path(path)
143
+ end
144
+
145
+ if loaded_config && ! @config["application_name"]
146
+ if @path
147
+ appname = File.basename(@path)
148
+ @config["application_name"] = appname
149
+ else
150
+ puts "You need application_name defined in your config!"
151
+ YAML.dump @config
152
+ exit 1
153
+ end
154
+ end
155
+
156
+ unless loaded_config
157
+ puts "Configuration Dump:\n\n"
158
+ puts YAML.dump(@config)
159
+ puts "I could not find a way to configure myself properly!\n"
160
+ puts opts.help
161
+ exit 1
162
+ end
163
+
164
+ if args.length > 1
165
+ puts "You specified more command line arguments than I can handle:"
166
+ puts args.join(" ")
167
+ puts opts.help
168
+ exit 1
169
+ end
170
+
171
+ if self.has_command?(args[0]) || args[0] == "create"
172
+ @command = args[0]
173
+ else
174
+ if args[0]
175
+ puts "#{args[0]} is not an allowed command"
176
+ else
177
+ puts "You must provide a command!"
178
+ end
179
+ puts opts.help
180
+ exit 1
181
+ end
182
+ end
183
+ end
184
+ end
@@ -0,0 +1,253 @@
1
+ # Created by Adam Jacob on 2007-03-21.
2
+ # Copyright (c) 2007. All rights reserved.
3
+
4
+ require 'mongrel_runit/base'
5
+
6
+ module MongrelRunit
7
+
8
+ # Represents a runit service directory for a particular mongrel.
9
+ #
10
+ # Example:
11
+ #
12
+ # service = MongrelRunit::Service.new(config)
13
+ # service.stop
14
+ # service.start
15
+ # service.create
16
+ #
17
+
18
+ class Service < Base
19
+ attr_reader :runfile, :logrunfile, :logconfig, :checkfile, :svdir, :config
20
+
21
+ # Takes a configuration hash as it's argument, ensures the
22
+ # runit_service_dir exists, and creates the runit_sv_dir.
23
+ def initialize(config)
24
+ @config = config
25
+
26
+ raise ArgumentError, "Must have an application_name!" unless @config.has_key?("application_name")
27
+ raise ArgumentError, "Must have a port!" unless @config.has_key?("port")
28
+ raise ArgumentError, "Must have a runit_sv_dir!" unless @config.has_key?("runit_sv_dir")
29
+ raise ArgumentError, "Must have a runit_service_dir!" unless @config.has_key?("runit_service_dir")
30
+
31
+ check_service_dir
32
+ make_sv_dir
33
+ end
34
+
35
+ # Catch-all for the common service commands. See MongrelRunit::Base for
36
+ # a list.
37
+ def method_missing(status)
38
+ if self.has_command?(status.id2name)
39
+ run(status.id2name)
40
+ else
41
+ Kernel.method_missing
42
+ end
43
+ end
44
+
45
+ # Returns true if the process is running, nil if it's not.
46
+ def is_running?
47
+ output, success = run("status")
48
+ output =~ /^run:/ ? true : nil
49
+ end
50
+
51
+ # Run a given command through sv.
52
+ def run(status)
53
+ cmd = "sv "
54
+ cmd += " -w #{@config['svwait']}" if @config.has_key?('svwait')
55
+ cmd += " #{status} #{@svdir}"
56
+ output = `#{cmd}`
57
+ return output, $?.success?
58
+ end
59
+
60
+ # Create the service directory for this mongrel. This includes the
61
+ # run script, log script, check script, and log config file. This
62
+ # should run any time there is a change to the configruation.
63
+ def create
64
+ make_run
65
+ make_check
66
+ make_log
67
+ make_log_config
68
+ link = make_service_link
69
+ return link, true
70
+ end
71
+
72
+ # Raises an exception if the runit_service_dir does not exist.
73
+ def check_service_dir
74
+ dir_exists = File.directory?(@config["runit_service_dir"])
75
+ raise ArgumentError, "runit_service_dir does not exist: #{@config["runit_service_dir"]}" unless dir_exists
76
+ dir_exists
77
+ end
78
+
79
+ # Creates the symlink between the mongrel's sv directory and the
80
+ # runit_service_dir.
81
+ def make_service_link
82
+ servicename = File.basename(@svdir)
83
+ link = File.expand_path(File.join(@config["runit_service_dir"], servicename))
84
+ unless File.symlink?(link)
85
+ `ln -s #{@svdir} #{@config["runit_service_dir"]}`
86
+ end
87
+ link
88
+ end
89
+
90
+ # Populates the check file, either with the contents of the checkfile
91
+ # configuration option, or:
92
+ #
93
+ # #!/usr/bin/env ruby
94
+ #
95
+ # require 'net/http'
96
+ #
97
+ # http = Net::HTTP.new('#{address}', #{@config["port"].to_i})
98
+ # begin
99
+ # response = http.options('/')
100
+ # if [Net::HTTPSuccess, Net::HTTPRedirection].any? {|klass| response = klass}
101
+ # exit 0
102
+ # else
103
+ # exit 1
104
+ # end
105
+ # rescue Errno::ECONNREFUSED
106
+ # exit 1
107
+ # end
108
+ def make_check
109
+ if @config.has_key?("checkfile")
110
+ @checkfile = interpret_line(@config["checkfile"])
111
+ else
112
+ @checkfile = <<EOH
113
+ #!/usr/bin/env ruby
114
+
115
+ require 'net/http'
116
+
117
+ http = Net::HTTP.new('#{@config['address']}', #{@config["port"].to_i})
118
+ begin
119
+ response = http.options('/')
120
+ if [Net::HTTPSuccess, Net::HTTPRedirection].any? {|klass| response = klass}
121
+ exit 0
122
+ else
123
+ exit 1
124
+ end
125
+ rescue Errno::ECONNREFUSED
126
+ exit 1
127
+ end
128
+ EOH
129
+ end
130
+ path_to_checkfile = File.expand_path(File.join(@svdir, "check"))
131
+ create_or_update_file(path_to_checkfile, @checkfile)
132
+ File.chmod(0755, path_to_checkfile)
133
+ path_to_checkfile
134
+ end
135
+
136
+ # Creates the sv direrectory for this mongrel. (From runit_sv_dir)
137
+ def make_sv_dir
138
+ @svdir = File.expand_path(File.join(
139
+ @config["runit_sv_dir"],
140
+ "mongrel-#{@config["application_name"]}-#{@config["port"]}"
141
+ ))
142
+ @svlogdir = File.expand_path(File.join(
143
+ @svdir, "log"
144
+ ))
145
+ `mkdir -p #{@svlogdir}`
146
+ raise "Cannot create #{@svlogdir}" unless $?.success?
147
+ @svlogdir
148
+ end
149
+
150
+ # If svlogd_config is defined, creates the log config file.
151
+ def make_log_config
152
+ path_to_file = nil
153
+ if @config.has_key?("svlogd_config")
154
+ path_to_file = File.expand_path(File.join(@svlogdir, "config"))
155
+ @logconfig = @config["svlogd_config"]
156
+ create_or_update_file(path_to_file, @logconfig)
157
+ end
158
+ path_to_file
159
+ end
160
+
161
+ # Makes the log run script.
162
+ def make_log
163
+ logdir = File.expand_path(File.join(@svlogdir, "main"))
164
+ if @config.has_key?("base_log_directory")
165
+ logdir = File.expand_path(File.join(
166
+ @config["base_log_directory"],
167
+ "#{@config[application_name]}-#{@config[port]}"
168
+ ))
169
+ end
170
+ `mkdir -p #{logdir}`
171
+ raise "Cannot create #{logdir}" unless $?.success?
172
+ @logrunfile = "#!/bin/sh\n"
173
+ @logrunfile << "exec svlogd -tt #{logdir}"
174
+ path_to_logrunfile = File.expand_path(File.join(@svlogdir, "run"))
175
+ create_or_update_file(path_to_logrunfile, @logrunfile)
176
+ File.chmod(0755, path_to_logrunfile)
177
+ path_to_logrunfile
178
+ end
179
+
180
+ # Makes the run script, which calls mongrel directly. The command
181
+ # line assembly code for mongrel_rails is taken verbatim from mongrel_cluster.
182
+ def make_run
183
+ cmd = if @config["command_line"]
184
+ interpret_line(@config["command_line"])
185
+ else
186
+ argv = [ "mongrel_rails" ]
187
+ argv << "start"
188
+ argv << "-e #{@config["environment"]}" if @config["environment"]
189
+ argv << "-p #{@config["port"]}"
190
+ argv << "-a #{@config["address"]}" if @config["address"]
191
+ argv << "-l #{@config["log_file"]}" if @config["log_file"]
192
+ argv << "-c #{File.expand_path(@config["cwd"])}" if @config["cwd"]
193
+ argv << "-t #{@config["timeout"]}" if @config["timeout"]
194
+ argv << "-m #{@config["mime_map"]}" if @config["mime_map"]
195
+ argv << "-r #{@config["docroot"]}" if @config["docroot"]
196
+ argv << "-n #{@config["num_procs"]}" if @config["num_procs"]
197
+ argv << "-B" if @config["debug"]
198
+ argv << "-S #{@config["config_script"]}" if @config["config_script"]
199
+ argv << "--user #{@config["user"]}" if @config["user"]
200
+ argv << "--group #{@config["group"]}" if @config["group"]
201
+ argv << "--prefix #{@config["prefix"]}" if @config["prefix"]
202
+ argv.join(" ")
203
+ end
204
+ env = nil
205
+ if @config.has_key?("env_vars")
206
+ env = "env"
207
+ @config["env_vars"].each do |key, value|
208
+ env << " #{key.upcase}=#{value}"
209
+ end
210
+ end
211
+ chpst = nil
212
+ if @config.has_key?("chpst")
213
+ chpst_command = `which chpst`.chomp
214
+ chpst = "#{chpst_command} #{@config['chpst']}"
215
+ end
216
+ @runfile = "#!/bin/sh\n"
217
+ @runfile << "exec \\\n"
218
+ @runfile << " #{env} \\\n" if env
219
+ @runfile << " #{chpst} \\\n" if chpst
220
+ @runfile << " #{cmd} 2>&1\n"
221
+
222
+ path_to_runfile = File.expand_path(File.join(@svdir, "run"))
223
+ create_or_update_file(path_to_runfile, @runfile)
224
+ File.chmod(0755, path_to_runfile)
225
+ path_to_runfile
226
+ end
227
+
228
+ private
229
+
230
+ def interpret_line(cmd)
231
+ begin
232
+ eval("\"#{cmd}\"")
233
+ rescue SyntaxError
234
+ puts "You have a syntax error in your string; perhaps you included a double quote without escaping it?"
235
+ raise
236
+ end
237
+ end
238
+
239
+ def create_or_update_file(file, new_contents)
240
+ write = 1
241
+ if File.file?(file)
242
+ current_contents = IO.read(file)
243
+ if current_contents == new_contents
244
+ write = nil
245
+ end
246
+ end
247
+
248
+ File.open(file, "w") do |file|
249
+ file.print(new_contents)
250
+ end if write
251
+ end
252
+ end
253
+ end