mongrel_service 0.1 → 0.4.beta1

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,52 @@
1
+ === 0.4.beta1 / 2010-01-01
2
+
3
+ * Enhancements:
4
+ * Removed win32-service dependency, making mongrel_service more portable
5
+ between Ruby implementations on Windows (One-Click and RubyInstaller)
6
+
7
+ * Now mongrel log files are written to the path specified by --log option.
8
+ Contribution by Daniel Gies (BigFix). Closes #44.
9
+
10
+ * Bugfixes:
11
+ * Wait longer for child process terminate properly (max 20 seconds).
12
+ Imported tests from RubyServices project. Closes #18.
13
+
14
+ * Workaround Windows 2008 process detection issues forcing 'service'
15
+ initialization parameter. Closes #54. [papillon]
16
+
17
+ * Updated ServiceFB to work with FB > 0.18.
18
+
19
+ === 0.3.4 / 2008-01-02
20
+
21
+ * Strict Gem dependencies for mongrel_service. This version is compatible
22
+ only with mongrel 1.0.x, 1.1.x and with win32-service 0.5.x.
23
+
24
+ * Fixed issues realted to Win32::Service and gem_plugin being registered with
25
+ different names due win32-service changes.
26
+
27
+ === 0.3.3 / 2007-10-26
28
+
29
+ * Properly display package/gem version for mongrel_service. Closes #13823.
30
+
31
+ * Updated ServiceFB to r80 to solve issue when compiling with FB > 0.17.
32
+
33
+ === 0.3.2 / 2007-06-01
34
+
35
+ * Solved detection of parent process at ServiceFB level
36
+ (solves the x64 Windows issues).
37
+
38
+ * Upgraded to ServiceFB 'trunk' (but pistoned it, just in case).
39
+
40
+ * Fixed problems with ruby installations outside PATH or inside folders with spaces.
41
+
42
+ * Activate FB pedantic warnings by default (is really useful).
43
+
44
+ === 0.3.1 / 2007-01-19
45
+
46
+ * Single Service (SingleMongrel) object type implemented.
47
+
48
+ * Updated Rakefile to reflect the new building steps.
49
+
50
+ * Removed SendSignal, too hackish for my taste, replaced with complete FB solution.
51
+
52
+ * Added basic Process monitoring and re-spawning.
data/LICENSE.txt ADDED
@@ -0,0 +1,55 @@
1
+ Mongrel Web Server (Mongrel) is copyrighted free software by Zed A. Shaw
2
+ <zedshaw at zedshaw dot com> and contributors. You can redistribute it
3
+ and/or modify it under either the terms of the GPL2 or the conditions below:
4
+
5
+ 1. You may make and give away verbatim copies of the source form of the
6
+ software without restriction, provided that you duplicate all of the
7
+ original copyright notices and associated disclaimers.
8
+
9
+ 2. You may modify your copy of the software in any way, provided that
10
+ you do at least ONE of the following:
11
+
12
+ a) place your modifications in the Public Domain or otherwise make them
13
+ Freely Available, such as by posting said modifications to Usenet or an
14
+ equivalent medium, or by allowing the author to include your
15
+ modifications in the software.
16
+
17
+ b) use the modified software only within your corporation or
18
+ organization.
19
+
20
+ c) rename any non-standard executables so the names do not conflict with
21
+ standard executables, which must also be provided.
22
+
23
+ d) make other distribution arrangements with the author.
24
+
25
+ 3. You may distribute the software in object code or executable
26
+ form, provided that you do at least ONE of the following:
27
+
28
+ a) distribute the executables and library files of the software,
29
+ together with instructions (in the manual page or equivalent) on where
30
+ to get the original distribution.
31
+
32
+ b) accompany the distribution with the machine-readable source of the
33
+ software.
34
+
35
+ c) give non-standard executables non-standard names, with
36
+ instructions on where to get the original software distribution.
37
+
38
+ d) make other distribution arrangements with the author.
39
+
40
+ 4. You may modify and include the part of the software into any other
41
+ software (possibly commercial). But some files in the distribution
42
+ are not written by the author, so that they are not under this terms.
43
+
44
+ 5. The scripts and library files supplied as input to or produced as
45
+ output from the software do not automatically fall under the
46
+ copyright of the software, but belong to whomever generated them,
47
+ and may be sold commercially, and may be aggregated with this
48
+ software.
49
+
50
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
51
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
52
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53
+ PURPOSE.
54
+
55
+
data/Manifest.txt ADDED
@@ -0,0 +1,32 @@
1
+ History.txt
2
+ lib/mongrel_service/init.rb
3
+ lib/mongrel_service/service_manager.rb
4
+ LICENSE.txt
5
+ Manifest.txt
6
+ Rakefile
7
+ README.txt
8
+ resources/defaults.yaml
9
+ resources/mongrel_service.exe
10
+ src/mongrel_service/_debug.bi
11
+ src/mongrel_service/boolean.bi
12
+ src/mongrel_service/console_process.bas
13
+ src/mongrel_service/console_process.bi
14
+ src/mongrel_service/mongrel_service.bas
15
+ src/mongrel_service/mongrel_service.bi
16
+ src/ServiceFB/_internals.bi
17
+ src/ServiceFB/_utils_internals.bi
18
+ src/ServiceFB/ServiceFB.bas
19
+ src/ServiceFB/ServiceFB.bi
20
+ src/ServiceFB/ServiceFB_Utils.bas
21
+ src/ServiceFB/ServiceFB_Utils.bi
22
+ tasks/gem.rake
23
+ tasks/native_lib.rake
24
+ tasks/native_service.rake
25
+ tasks/tests.rake
26
+ tests/all_tests.bas
27
+ tests/fixtures/mock_process.bas
28
+ tests/test_console_process.bas
29
+ tests/test_helpers.bas
30
+ tests/test_helpers.bi
31
+ TODO.txt
32
+ tools/freebasic.rb
data/README.txt ADDED
@@ -0,0 +1,20 @@
1
+ = Mongrel Native Win32 Service Plugin
2
+
3
+ * http://github.com/fauna/mongrel_service
4
+
5
+ == DESCRIPTION
6
+
7
+ This plugin offer native win32 services for rails.
8
+ This replace mongrel_rails_service.
9
+
10
+ == USAGE
11
+
12
+ Use the following commands to get more help:
13
+
14
+ service::install --help
15
+ service::remove --help
16
+ service::update --help
17
+
18
+ == AUTHOR
19
+
20
+ Luis Lavena
data/Rakefile CHANGED
@@ -1,42 +1,8 @@
1
- require 'rake'
2
- require 'rake/testtask'
3
- require 'rake/clean'
4
- require 'rake/gempackagetask'
5
- require 'rake/rdoctask'
6
- require 'tools/rakehelp'
7
- require 'fileutils'
8
- include FileUtils
9
-
10
- setup_tests
11
- setup_clean ["pkg", "lib/*.bundle", "*.gem", ".config"]
12
-
13
- setup_rdoc ['README', 'LICENSE', 'COPYING', 'lib/**/*.rb', 'doc/**/*.rdoc']
14
-
15
- desc "Does a full compile, test run"
16
- task :default => [:test, :package]
17
-
18
- version="0.1"
19
- name="mongrel_service"
20
-
21
- setup_gem(name, version) do |spec|
22
- spec.summary = "Mongrel Native Win32 Service Plugin for Rails"
23
- spec.description = "This plugin offer native win32 services for rails, powered by Mongrel."
24
- spec.author="Luis Lavena"
25
-
26
- # added mongrel_service executable
27
- spec.executables = ["mongrel_service"]
28
-
29
- spec.add_dependency('gem_plugin', '>= 0.2.1')
30
- spec.add_dependency('mongrel', '>= 0.3.12.4')
31
- spec.files += Dir.glob("resources/**/*")
32
- end
33
-
34
-
35
- task :install => [:test, :package] do
36
- sh %{gem install pkg/#{name}-#{version}.gem}
37
- end
38
-
39
- task :uninstall => [:clean] do
40
- sh %{gem uninstall #{name}}
41
- end
42
-
1
+ #
2
+ # NOTE: Keep this file clean.
3
+ # Add your customizations inside tasks directory.
4
+ # Thank You.
5
+ #
6
+
7
+ # load rakefile extensions (tasks)
8
+ Dir['tasks/*.rake'].sort.each { |f| load f }
data/TODO.txt ADDED
@@ -0,0 +1,19 @@
1
+ Legend:
2
+ [ ] not done
3
+ [X] done
4
+ [+] in progess
5
+
6
+ ### General
7
+ [ ] Add more documentation about services and requirements
8
+ [ ] Add process monitoring.
9
+
10
+ ### Dependencies
11
+ [+] Remove win32/service extension dependency (instead of relying in the non-official 0.5.0 one).
12
+ [ ] Add service management (from ServiceFB) to install and remove services.
13
+
14
+ ### SingleMongrel
15
+ [+] Sanitize SingleMongrel and document the functions.
16
+
17
+ ### ClusterMongrel
18
+ [ ] Parse mongrel_cluster configuration file (yaml) looking for port information
19
+ [ ] Reimplent SingleMongrel for ClusterMongrel, splitting source files for better organization.
@@ -2,8 +2,8 @@ require 'gem_plugin'
2
2
  require 'mongrel'
3
3
  require 'mongrel/rails'
4
4
  require 'rbconfig'
5
- require 'win32/service'
6
-
5
+ require 'fileutils'
6
+ require 'mongrel_service/service_manager'
7
7
 
8
8
  module Service
9
9
  class Install < GemPlugin::Plugin "/commands"
@@ -26,7 +26,7 @@ module Service
26
26
  ['-B', '--debug', "Enable debugging mode", :@debug, false],
27
27
  ['-C', '--config PATH', "Use a config file", :@config_file, nil],
28
28
  ['-S', '--script PATH', "Load the given file as an extra config script.", :@config_script, nil],
29
- ['-u', '--cpu CPU', "Bind the process to specific cpu, starting from 1.", :@cpu, nil]
29
+ ['', '--prefix PATH', "URL prefix for Rails app", :@prefix, nil]
30
30
  ]
31
31
  end
32
32
 
@@ -42,13 +42,15 @@ module Service
42
42
 
43
43
  # start with the premise of app really exist.
44
44
  app_exist = true
45
- %w{app config db log public}.each do |path|
45
+ %w{app config log}.each do |path|
46
46
  if !File.directory?(File.join(@cwd, path))
47
47
  app_exist = false
48
48
  break
49
49
  end
50
50
  end
51
51
 
52
+ valid?(@prefix[0].chr == "/" && @prefix[-1].chr != "/", "Prefix must begin with / and not end in /") if @prefix
53
+
52
54
  valid? app_exist == true, "The path you specified isn't a valid Rails application."
53
55
 
54
56
  valid_dir? File.dirname(@log_file), "Path to log file not valid: #@log_file"
@@ -57,12 +59,9 @@ module Service
57
59
  valid_exists? @mime_map, "MIME mapping file does not exist: #@mime_map" if @mime_map
58
60
  valid_exists? @config_file, "Config file not there: #@config_file" if @config_file
59
61
 
60
- # Validate the number of cpu to bind to.
61
- valid? @cpu.to_i > 0, "You must specify a numeric value for cpu. (1..8)" if @cpu
62
-
63
62
  # We should validate service existance here, right Zed?
64
63
  begin
65
- valid? !Win32::Service.exists?(@svc_name), "The service already exist, please remove it first."
64
+ valid? !ServiceManager.exist?(@svc_name), "The service already exist, please remove it first."
66
65
  rescue
67
66
  end
68
67
 
@@ -75,57 +74,82 @@ module Service
75
74
  end
76
75
 
77
76
  def run
77
+ # check if mongrel_service.exe is in ruby bindir.
78
+ gem_root = File.join(File.dirname(__FILE__), "..", "..")
79
+ gem_executable = File.join(gem_root, "resources/mongrel_service.exe")
80
+ bindir_executable = File.join(Config::CONFIG['bindir'], '/mongrel_service.exe')
81
+
82
+ unless File.exist?(bindir_executable)
83
+ STDERR.puts "** Copying native mongrel_service executable..."
84
+ FileUtils.cp gem_executable, bindir_executable rescue nil
85
+ end
86
+
87
+ unless FileUtils.compare_file(bindir_executable, gem_executable)
88
+ STDERR.puts "** Updating native mongrel_service executable..."
89
+ FileUtils.rm_f bindir_executable rescue nil
90
+ FileUtils.cp gem_executable, bindir_executable rescue nil
91
+ end
92
+
93
+ # build the command line
94
+ argv = []
95
+
96
+ # start using the native executable
97
+ argv << '"' + bindir_executable + '"'
98
+
99
+ # force indication of service mode (workaround Windows 2008 psapi issue)
100
+ argv << "service"
101
+
102
+ # use the 'single' service for now
103
+ argv << "single"
104
+
78
105
  # command line setting override config file settings
79
106
  @options = { :host => @address, :port => @port, :cwd => @cwd,
80
107
  :log_file => @log_file, :pid_file => @pid_file, :environment => @environment,
81
108
  :docroot => @docroot, :mime_map => @mime_map,
82
109
  :debug => @debug, :includes => ["mongrel"], :config_script => @config_script,
83
- :num_procs => @num_procs, :timeout => @timeout, :cpu => @cpu
110
+ :num_procs => @num_procs, :timeout => @timeout, :cpu => @cpu, :prefix => @prefix
84
111
  }
85
-
112
+
113
+ # if we are using a config file, pass -c and -C to the service instead of each start parameter.
86
114
  if @config_file
87
- STDERR.puts "** Loading settings from #{@config_file} (command line options override)."
115
+ STDERR.puts "** Using #{@config_file} instead of command line parameters."
88
116
  conf = YAML.load_file(@config_file)
89
- @options = conf.merge(@options)
117
+
118
+ # add the root folder (-c)
119
+ argv << "-c \"#{conf[:cwd]}\""
120
+
121
+ # use the config file
122
+ argv << "-C \"#{@config_file}\""
123
+
124
+ else
125
+ # use the command line instead
126
+ # now the options
127
+ argv << "-e #{@options[:environment]}" if @options[:environment]
128
+ argv << "-p #{@options[:port]}"
129
+ argv << "-a #{@options[:host]}" if @options[:host]
130
+ argv << "-l \"#{@options[:log_file]}\"" if @options[:log_file]
131
+ argv << "-P \"#{@options[:pid_file]}\""
132
+ argv << "-c \"#{@options[:cwd]}\"" if @options[:cwd]
133
+ argv << "-t #{@options[:timeout]}" if @options[:timeout]
134
+ argv << "-m \"#{@options[:mime_map]}\"" if @options[:mime_map]
135
+ argv << "-r \"#{@options[:docroot]}\"" if @options[:docroot]
136
+ argv << "-n #{@options[:num_procs]}" if @options[:num_procs]
137
+ argv << "-B" if @options[:debug]
138
+ argv << "-S \"#{@options[:config_script]}\"" if @options[:config_script]
139
+ argv << "-u #{@options[:cpu.to_i]}" if @options[:cpu]
140
+ argv << "--prefix \"#{@options[:prefix]}\"" if @options[:prefix]
90
141
  end
91
142
 
92
- argv = []
93
-
94
- # ruby.exe instead of rubyw.exe due a exception raised when stoping the service!
95
- argv << '"' + Config::CONFIG['bindir'] + '/ruby.exe' + '"'
96
-
97
- # add service_script, we now use the rubygem powered one
98
- argv << '"' + Config::CONFIG['bindir'] + '/mongrel_service' + '"'
99
-
100
- # now the options
101
- argv << "-e #{@options[:environment]}" if @options[:environment]
102
- argv << "-p #{@options[:port]}"
103
- argv << "-a #{@options[:address]}" if @options[:address]
104
- argv << "-l \"#{@options[:log_file]}\"" if @options[:log_file]
105
- argv << "-P \"#{@options[:pid_file]}\""
106
- argv << "-c \"#{@options[:cwd]}\"" if @options[:cwd]
107
- argv << "-t #{@options[:timeout]}" if @options[:timeout]
108
- argv << "-m \"#{@options[:mime_map]}\"" if @options[:mime_map]
109
- argv << "-r \"#{@options[:docroot]}\"" if @options[:docroot]
110
- argv << "-n #{@options[:num_procs]}" if @options[:num_procs]
111
- argv << "-B" if @options[:debug]
112
- argv << "-S \"#{@options[:config_script]}\"" if @options[:config_script]
113
- argv << "-u #{@options[:cpu.to_i]}" if @options[:cpu]
114
-
115
- svc = Win32::Service.new
116
143
  begin
117
- svc.create_service{ |s|
118
- s.service_name = @svc_name
119
- s.display_name = @svc_display
120
- s.binary_path_name = argv.join ' '
121
- s.dependencies = []
122
- }
123
- puts "Mongrel service '#{@svc_display}' installed as '#{@svc_name}'."
124
- rescue Win32::ServiceError => err
144
+ ServiceManager.create(
145
+ @svc_name,
146
+ @svc_display,
147
+ argv.join(' ')
148
+ )
149
+ rescue ServiceManager::CreateError => e
125
150
  puts "There was a problem installing the service:"
126
- puts err
151
+ puts e
127
152
  end
128
- svc.close
129
153
  end
130
154
  end
131
155
 
@@ -138,13 +162,15 @@ module Service
138
162
 
139
163
  def validate
140
164
  valid? @svc_name != nil, "A service name is mandatory."
141
-
165
+
142
166
  # Validate that the service exists
143
- begin
144
- valid? Win32::Service.exists?(@svc_name), "There is no service with that name, cannot proceed."
145
- rescue
167
+ valid? ServiceManager.exist?(@svc_name), "There is no service with that name, cannot proceed."
168
+ if @valid then
169
+ ServiceManager.open(@svc_name) do |svc|
170
+ valid? svc.binary_path_name.include?("mongrel_service"), "The service specified isn't a Mongrel service."
171
+ end
146
172
  end
147
-
173
+
148
174
  return @valid
149
175
  end
150
176
  end
@@ -152,69 +178,24 @@ module Service
152
178
  class Remove < GemPlugin::Plugin "/commands"
153
179
  include Mongrel::Command::Base
154
180
  include ServiceValidation
155
-
181
+
156
182
  def run
157
- display_name = Win32::Service.getdisplayname(@svc_name)
158
-
183
+ display_name = ServiceManager.getdisplayname(@svc_name)
184
+
159
185
  begin
160
- Win32::Service.stop(@svc_name)
161
- rescue
186
+ ServiceManager.stop(@svc_name)
187
+ rescue ServiceManager::ServiceError => e
162
188
  end
163
- begin
164
- Win32::Service.delete(@svc_name)
165
- rescue
166
- end
167
- puts "#{display_name} service removed."
168
- end
169
- end
170
189
 
171
- class Start < GemPlugin::Plugin "/commands"
172
- include Mongrel::Command::Base
173
- include ServiceValidation
174
-
175
- def run
176
- display_name = Win32::Service.getdisplayname(@svc_name)
177
-
178
190
  begin
179
- Win32::Service.start(@svc_name)
180
- started = false
181
- while started == false
182
- s = Win32::Service.status(@svc_name)
183
- started = true if s.current_state == "running"
184
- break if started == true
185
- puts "One moment, " + s.current_state
186
- sleep 1
187
- end
188
- puts "#{display_name} service started"
189
- rescue Win32::ServiceError => err
190
- puts "There was a problem starting the service:"
191
- puts err
191
+ ServiceManager.delete(@svc_name)
192
+ rescue ServiceManager::ServiceError => e
193
+ puts e
192
194
  end
193
- end
194
- end
195
195
 
196
- class Stop < GemPlugin::Plugin "/commands"
197
- include Mongrel::Command::Base
198
- include ServiceValidation
199
-
200
- def run
201
- display_name = Win32::Service.getdisplayname(@svc_name)
202
-
203
- begin
204
- Win32::Service.stop(@svc_name)
205
- stopped = false
206
- while stopped == false
207
- s = Win32::Service.status(@svc_name)
208
- stopped = true if s.current_state == "stopped"
209
- break if stopped == true
210
- puts "One moment, " + s.current_state
211
- sleep 1
212
- end
213
- puts "#{display_name} service stopped"
214
- rescue Win32::ServiceError => err
215
- puts "There was a problem stopping the service:"
216
- puts err
196
+ unless ServiceManager.exist?(@svc_name) then
197
+ puts "#{display_name} service removed."
217
198
  end
218
199
  end
219
200
  end
220
- end
201
+ end