daemon_controller 1.2.0 → 2.0.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.
- checksums.yaml +5 -13
- data/LICENSE.txt +1 -2
- data/{README.markdown → README.md} +40 -76
- data/Rakefile +16 -574
- data/daemon_controller.gemspec +5 -4
- data/lib/daemon_controller/lock_file.rb +106 -105
- data/lib/daemon_controller/packaging.rb +10 -16
- data/lib/daemon_controller/spawn.rb +8 -7
- data/lib/daemon_controller/version.rb +10 -8
- data/lib/daemon_controller.rb +941 -851
- data/spec/daemon_controller_spec.rb +572 -409
- data/spec/echo_server.rb +139 -115
- data/spec/test_helper.rb +132 -105
- data/spec/unresponsive_daemon.rb +13 -7
- metadata +7 -20
- checksums.yaml.gz.asc +0 -12
- data/debian.template/changelog +0 -5
- data/debian.template/compat +0 -1
- data/debian.template/control.template +0 -15
- data/debian.template/copyright +0 -24
- data/debian.template/ruby-daemon-controller.install +0 -2
- data/debian.template/rules +0 -17
- data/debian.template/source/format +0 -1
- data/rpm/get_distro_id.py +0 -4
- data/rpm/rubygem-daemon_controller.spec.template +0 -102
- data.tar.gz.asc +0 -12
- metadata.gz.asc +0 -12
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
MTUyNDIxMmExMmNlMTFjOWQ1ZjVhODdmM2ExOTUwMTQ2YTk0MjM2MQ==
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c9dce68cae7ce8da028c91815950481313672404aeaa48a0b97e817263dbb5ff
|
4
|
+
data.tar.gz: 921a96fe368c826fa881e2beecab2a298620249b4a76bf1934849a22ea5bb61c
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
ODBmMGQxMWIwYTc3ZmRlYTJlZmQwNGNiOGQ1MmZiNDE2MzI1NTFjZGY3NjE3
|
11
|
-
MWQ1ZjExYzc1ZTI2MDM3YTc2ZjhhZjJmMGFkZDZkMTY2NTQzYmI=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
ZWI1NmQ1Y2U5NjRlZGUxZDE0ODA3NTMwMDQ2NWM5NjlkMjYxZTgxYTFkYTA2
|
14
|
-
ZWY2NjUxYjczZTQ5YWJjODM1MWZlODQxY2UyOTc2M2I5NjVmOGUwNTZmMWNl
|
15
|
-
MGZkZTUwODg0NDFjNmU2MzZlODI2ZTZhZmZiMmYwYjEwMWQ1ZDg=
|
6
|
+
metadata.gz: 27a36b21d30836e901637ea07f538872fa306f9ce9bfacd6175b0b4858ac45ba825999d798e9e7740371148f47e93d212df9f16a326835385613730e69389c65
|
7
|
+
data.tar.gz: 23acb3cee9eef3f771f42e8deb06c750ba8bb4aa04d58bfa6b24837a15ff928edbe97c56b4f2018aed142e600f5f26733afc7e01bc1b1941f127d5e9d068142e
|
data/LICENSE.txt
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c) 2008-
|
1
|
+
Copyright (c) 2008-2025 Asynchronous B.V.
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
4
|
of this software and associated documentation files (the "Software"), to deal
|
@@ -17,4 +17,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
17
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
18
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
19
|
THE SOFTWARE.
|
20
|
-
|
@@ -12,11 +12,11 @@ It provides the following functionality:
|
|
12
12
|
* Starting daemons. If the daemon fails to start then an exception will be
|
13
13
|
raised. *daemon_controller* can even detect failures that occur after the
|
14
14
|
daemon has already daemonized.
|
15
|
-
|
15
|
+
|
16
16
|
Starting daemons is done in a race-condition-free manner. If another
|
17
17
|
process using *daemon_controller* is trying to start the same daemon,
|
18
18
|
then *daemon_controller* will guarantee serialization.
|
19
|
-
|
19
|
+
|
20
20
|
*daemon_controller* also raises an exception if it detects that the daemon
|
21
21
|
is already started.
|
22
22
|
* Connecting to a daemon, starting it if it's not already started. This too
|
@@ -25,47 +25,11 @@ It provides the following functionality:
|
|
25
25
|
* Stopping daemons.
|
26
26
|
* Checking whether a daemon is running.
|
27
27
|
|
28
|
-
## Installation
|
29
|
-
|
30
|
-
gem install daemon_controller
|
31
|
-
|
32
|
-
This gem is signed using PGP with the [Phusion Software Signing key](http://www.phusion.nl/about/gpg). That key in turn is signed by [the rubygems-openpgp Certificate Authority](http://www.rubygems-openpgp-ca.org/).
|
33
|
-
|
34
|
-
You can verify the authenticity of the gem by following [The Complete Guide to Verifying Gems with rubygems-openpgp](http://www.rubygems-openpgp-ca.org/blog/the-complete-guide-to-verifying-gems-with-rubygems-openpgp.html).
|
35
|
-
|
36
|
-
## Installation on Ubuntu
|
37
|
-
|
38
|
-
Use our [PPA](https://launchpad.net/~phusion.nl/+archive/misc):
|
39
|
-
|
40
|
-
sudo add-apt-repository ppa:phusion.nl/misc
|
41
|
-
sudo apt-get update
|
42
|
-
sudo apt-get install ruby-daemon-controller
|
43
|
-
|
44
|
-
## Installation on Debian
|
45
|
-
|
46
|
-
Our Ubuntu Lucid packages are compatible with Debian 6.
|
28
|
+
## Installation
|
47
29
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
sudo apt-get update
|
52
|
-
sudo apt-get install ruby-daemon-controller
|
53
|
-
|
54
|
-
## Installation on RHEL, CentOS and Amazon Linux
|
55
|
-
|
56
|
-
Enable our YUM repository:
|
57
|
-
|
58
|
-
# RHEL 6, CentOS 6
|
59
|
-
curl -L https://oss-binaries.phusionpassenger.com/yumgems/phusion-misc/el.repo | \
|
60
|
-
sudo tee /etc/yum.repos.d/phusion-misc.repo
|
61
|
-
|
62
|
-
# Amazon Linux
|
63
|
-
curl -L https://oss-binaries.phusionpassenger.com/yumgems/phusion-misc/amazon.repo | \
|
64
|
-
sudo tee /etc/yum.repos.d/phusion-misc.repo
|
65
|
-
|
66
|
-
Install our package:
|
67
|
-
|
68
|
-
sudo yum install rubygem-daemon_controller
|
30
|
+
```bash
|
31
|
+
gem install daemon_controller
|
32
|
+
```
|
69
33
|
|
70
34
|
## Resources
|
71
35
|
|
@@ -168,11 +132,11 @@ From the problem descriptions, it would become apparent that our wishlist is as
|
|
168
132
|
follows. Why is this wishlist often not implemented? Let's go over them.
|
169
133
|
|
170
134
|
- **A daemon should be automatically started on demand, instead of requiring the user to manually start it.**
|
171
|
-
|
135
|
+
|
172
136
|
The most obvious problems are related to concurrency. Suppose that your web
|
173
137
|
application has a search box, and you want to start the search daemon if it
|
174
138
|
isn't already started, then connect to. Two problems will arise:
|
175
|
-
|
139
|
+
|
176
140
|
* Suppose that Rails process A is still starting the daemon. At the same
|
177
141
|
time, another visitor tries to search something, and Rails process B
|
178
142
|
notices that the daemon is not running. If B tries to start the daemon
|
@@ -183,24 +147,24 @@ follows. Why is this wishlist often not implemented? Let's go over them.
|
|
183
147
|
start. For example, if you wait 2 seconds, then try to connect to the
|
184
148
|
daemon, and the daemon isn't done initializing yet, then it will seem as
|
185
149
|
if the daemon failed to start.
|
186
|
-
|
150
|
+
|
187
151
|
These are the most probable reasons why people don't try to write
|
188
152
|
auto-starting code, and instead require the user to start the daemon
|
189
153
|
manually.
|
190
|
-
|
154
|
+
|
191
155
|
These problems, as well as several less obvious problems, are closely
|
192
156
|
related to the next few points.
|
193
|
-
|
157
|
+
|
194
158
|
- **The daemon starter must wait until the daemon is done initializing, no longer and no shorter**
|
195
|
-
|
159
|
+
|
196
160
|
Because only after the daemon is fully initialized, is it safe to connect
|
197
161
|
to it. And because the user should not have to wait longer than he really
|
198
162
|
has to. During startup, the daemon will have to be continuously checked
|
199
163
|
whether it's done initializing or whether an error occured. Writing this
|
200
164
|
code can be quite a hassle, which is why most people don't do it.
|
201
|
-
|
165
|
+
|
202
166
|
- **The daemon starter must report any startup errors**
|
203
|
-
|
167
|
+
|
204
168
|
If the daemon starting command - e.g. `sphinx -c config_file.conf`,
|
205
169
|
`apachectl start` or `mongrel_rails cluster::start` - reports startup
|
206
170
|
errors, then all is fine as long as the user is starting the command from a
|
@@ -208,16 +172,16 @@ follows. Why is this wishlist often not implemented? Let's go over them.
|
|
208
172
|
already gone into the background. Such errors are only reported to the log
|
209
173
|
file.
|
210
174
|
*The daemon starter should also check the log file for any startup errors.*
|
211
|
-
|
175
|
+
|
212
176
|
Furthermore, it should be able to raise startup errors as exceptions. This
|
213
177
|
allows the the application to decide what to do with the error. For less
|
214
178
|
experienced system administrators, the error might be displayed in the
|
215
179
|
browser, allowing the administrators to become aware of the problem without
|
216
180
|
forcing them to manually check the log files. Or the error might be emailed
|
217
181
|
to a system administrator's email address.
|
218
|
-
|
182
|
+
|
219
183
|
- **The daemon starter must be able to correct stale or corrupted PID files**
|
220
|
-
|
184
|
+
|
221
185
|
If the PID file is stale, or for some reason has been corrupted, then the
|
222
186
|
daemon starter must be able to cope with that.
|
223
187
|
*It should check whether the PID file contains a valid PID, and whether the PID exists.*
|
@@ -292,28 +256,28 @@ or [God](http://god.rubyforge.org/). Rather, it is a solution to the following
|
|
292
256
|
problem:
|
293
257
|
|
294
258
|
> **Hongli:** hey Ninh, do a 'git pull', I just implemented awesome searching
|
295
|
-
> features in our application!
|
296
|
-
> **Ninh:** cool. *pulls from repository*
|
297
|
-
> **Ninh:** hey Hongli, it doesn't work.
|
298
|
-
> **Hongli:** what do you mean, it doesn't work?
|
299
|
-
> **Ninh:** it says "connection refused", or something
|
259
|
+
> features in our application!
|
260
|
+
> **Ninh:** cool. *pulls from repository*
|
261
|
+
> **Ninh:** hey Hongli, it doesn't work.
|
262
|
+
> **Hongli:** what do you mean, it doesn't work?
|
263
|
+
> **Ninh:** it says "connection refused", or something
|
300
264
|
> **Hongli:** oh I forgot to mention it, you have to run the Sphinx search
|
301
265
|
> daemon before it works. type "rake sphinx:daemon:start" to do
|
302
|
-
> that
|
266
|
+
> that
|
303
267
|
> **Ninh:** great. but now I get a different error. something about
|
304
|
-
> BackgrounDRb.
|
268
|
+
> BackgrounDRb.
|
305
269
|
> **Hongli:** oops, I forgot to mention this too. you need to start the
|
306
|
-
> BackgrounDRb server with "rake backgroundrb:start_server"
|
270
|
+
> BackgrounDRb server with "rake backgroundrb:start_server"
|
307
271
|
> **Ninh:** okay, so every time I want to use this app, I have to type
|
308
272
|
> "rake sphinx:daemon:start", "rake backgroundrb:start_server" and
|
309
|
-
> "./script/server"?
|
273
|
+
> "./script/server"?
|
310
274
|
> **Hongli:** yep
|
311
275
|
|
312
276
|
Imagine the above conversation becoming just:
|
313
277
|
|
314
278
|
> **Hongli:** hey Ninh, do a 'git pull', I just implemented awesome searching
|
315
|
-
> features in our application!
|
316
|
-
> **Ninh:** cool. *pulls from repository*
|
279
|
+
> features in our application!
|
280
|
+
> **Ninh:** cool. *pulls from repository*
|
317
281
|
> **Ninh:** awesome, it works!
|
318
282
|
|
319
283
|
This is not something that can be achieved with Monit/God. Monit/God are for
|
@@ -343,14 +307,14 @@ server must be running. For every test, you will want the unit test suite to:
|
|
343
307
|
That can be done with the following code:
|
344
308
|
|
345
309
|
require 'daemon_controller'
|
346
|
-
|
310
|
+
|
347
311
|
File.open("apache.conf", "w") do |f|
|
348
312
|
f.write("PidFile apache.pid\n")
|
349
313
|
f.write("LogFile apache.log\n")
|
350
314
|
f.write("Listen 1234\n")
|
351
315
|
f.write(... other relevant configuration options ...)
|
352
316
|
end
|
353
|
-
|
317
|
+
|
354
318
|
controller = DaemonController.new(
|
355
319
|
:identifier => 'Apache web server',
|
356
320
|
:start_command => 'apachectl -f apache.conf -k start',
|
@@ -360,10 +324,10 @@ That can be done with the following code:
|
|
360
324
|
:start_timeout => 25
|
361
325
|
)
|
362
326
|
controller.start
|
363
|
-
|
327
|
+
|
364
328
|
.... apache is now started ....
|
365
329
|
.... some test code here ....
|
366
|
-
|
330
|
+
|
367
331
|
controller.stop
|
368
332
|
|
369
333
|
The `File.open` line is obvious: it writes the relevant Apache configuration
|
@@ -429,10 +393,10 @@ isn't running.
|
|
429
393
|
This can be achieved with the following code:
|
430
394
|
|
431
395
|
require 'daemon_controller'
|
432
|
-
|
396
|
+
|
433
397
|
class SearchServer
|
434
398
|
SEARCH_SERVER_PORT = 1234
|
435
|
-
|
399
|
+
|
436
400
|
def initialize
|
437
401
|
@controller = DaemonController.new(
|
438
402
|
:identifier => 'Sphinx search server',
|
@@ -442,7 +406,7 @@ This can be achieved with the following code:
|
|
442
406
|
:pid_file => 'tmp/pids/sphinx.pid',
|
443
407
|
:log_file => 'log/sphinx.log')
|
444
408
|
end
|
445
|
-
|
409
|
+
|
446
410
|
def query(search_terms)
|
447
411
|
socket = @controller.connect do
|
448
412
|
TCPSocket.new('localhost', SEARCH_SERVER_PORT)
|
@@ -450,7 +414,7 @@ This can be achieved with the following code:
|
|
450
414
|
send_query(socket, search_terms)
|
451
415
|
return retrieve_results(socket)
|
452
416
|
end
|
453
|
-
|
417
|
+
|
454
418
|
private
|
455
419
|
def before_start
|
456
420
|
generate_configuration_file
|
@@ -458,7 +422,7 @@ This can be achieved with the following code:
|
|
458
422
|
generate_index
|
459
423
|
end
|
460
424
|
end
|
461
|
-
|
425
|
+
|
462
426
|
...
|
463
427
|
end
|
464
428
|
|
@@ -506,11 +470,11 @@ synchronization. This has a few implications:
|
|
506
470
|
Multiple threads can safely use daemon_controller concurrently. Multiple
|
507
471
|
processes can safely use daemon_controller concurrently. There will be no
|
508
472
|
race conditions.
|
509
|
-
|
473
|
+
|
510
474
|
However `flock()` is not implemented on Solaris. daemon_controller, if
|
511
475
|
used in MRI does not currently work on Solaris. You need to use JRuby
|
512
476
|
which does not use `flock()` to implement `File#flock`.
|
513
|
-
|
477
|
+
|
514
478
|
* On JRuby `File#flock` is implemented through the Java file locking API,
|
515
479
|
which on Unix is implemented with the `fcntl()` system calls. This is a
|
516
480
|
different kind of lock with very strange semantics.
|
@@ -524,7 +488,7 @@ synchronization. This has a few implications:
|
|
524
488
|
cannot be used to synchronize threads. If a thread has obtained a file
|
525
489
|
lock, then another thread within the same JVM process will not block upon
|
526
490
|
trying to lock the same file.
|
527
|
-
|
491
|
+
|
528
492
|
In other words, if you're on JRuby then don't concurrently access
|
529
493
|
daemon_controller from multiple threads without manual locking. Also be
|
530
494
|
careful with mixing MRI processes that use daemon_controller with JRuby
|