daemontor 0.0.1 → 1.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.
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/{README.rdoc → README.md} +20 -19
- data/Rakefile +2 -25
- data/daemontor.gemspec +18 -0
- data/examples/town_crier.rb +19 -19
- data/lib/daemontor.rb +57 -82
- data/lib/daemontor/version.rb +3 -0
- data/spec/daemontor_spec.rb +27 -27
- data/spec/spec_helper.rb +22 -31
- metadata +40 -83
- data.tar.gz.sig +0 -2
- data/COPYING.txt +0 -674
- data/History.txt +0 -4
- data/Manifest.txt +0 -15
- data/preamble +0 -19
- data/script/console +0 -10
- data/script/destroy +0 -14
- data/script/generate +0 -14
- data/spec/spec.opts +0 -1
- data/tasks/rspec.rake +0 -21
- metadata.gz.sig +0 -1
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Dan Wanek
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/{README.rdoc → README.md}
RENAMED
@@ -1,33 +1,34 @@
|
|
1
|
-
|
1
|
+
h1. Daemontor
|
2
2
|
|
3
3
|
* http://github.com/zenchild/daemontor
|
4
4
|
|
5
|
-
|
5
|
+
h2. DESCRIPTION
|
6
6
|
|
7
7
|
If you are looking for a package that allows you to simply run a process in the background, Deamontor can help you out. If you're looking for a package that does threading and fine grain process control you'll probably want to look elsewhere.
|
8
8
|
|
9
|
-
|
9
|
+
h2. DEPENDENCIES
|
10
10
|
|
11
11
|
This module depends on the fork system call so it will not run on a Windows OS.
|
12
12
|
|
13
|
-
|
13
|
+
h2. SYNOPSIS
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
15
|
+
```ruby
|
16
|
+
require 'rubygems'
|
17
|
+
require 'daemontor'
|
18
|
+
class Test
|
19
|
+
include Daemontor
|
20
|
+
def initialize
|
21
|
+
daemonize!
|
22
|
+
end
|
23
|
+
end
|
24
|
+
Test.new
|
25
|
+
```
|
24
26
|
|
25
|
-
|
27
|
+
**Also see code in examples/**
|
26
28
|
|
27
|
-
|
29
|
+
h2. INSTALL
|
28
30
|
|
29
|
-
|
31
|
+
`gem install daemontor` or `bundle install`
|
30
32
|
|
31
|
-
|
32
|
-
|
33
|
-
This project is licensed under GPLv3. See COPYING.txt for details.
|
33
|
+
h2. LICENSE
|
34
|
+
This project is licensed under the MIT license (See LICENSE for details).
|
data/Rakefile
CHANGED
@@ -1,25 +1,2 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'hoe'
|
4
|
-
require 'fileutils'
|
5
|
-
require './lib/daemontor'
|
6
|
-
|
7
|
-
Hoe.plugin :newgem
|
8
|
-
# Hoe.plugin :website
|
9
|
-
# Hoe.plugin :cucumberfeatures
|
10
|
-
|
11
|
-
# Generate all the Rake tasks
|
12
|
-
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
13
|
-
$hoe = Hoe.spec 'daemontor' do
|
14
|
-
self.developer 'Dan Wanek', 'dan.wanek@gmail.com'
|
15
|
-
self.rubyforge_name = nil
|
16
|
-
self.spec_extras[:licenses] = "GPLv3"
|
17
|
-
# self.extra_deps = [['activesupport','>= 2.0.2']]
|
18
|
-
end
|
19
|
-
|
20
|
-
require 'newgem/tasks'
|
21
|
-
Dir['tasks/**/*.rake'].each { |t| load t }
|
22
|
-
|
23
|
-
# TODO - want other tests/tasks run by default? Add them to the list
|
24
|
-
# remove_task :default
|
25
|
-
# task :default => [:spec, :features]
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler/gem_tasks"
|
data/daemontor.gemspec
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/daemontor/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Dan Wanek"]
|
6
|
+
gem.email = ["dan.wanek@gmail.com"]
|
7
|
+
gem.description = %q{Module to aid in running background processes.}
|
8
|
+
gem.summary = %q{If you are looking for a gem that allows you to simply run a process in the background, Deamontor can help you out. If you're looking for a package that does threading and fine grain process control you'll probably want to look elsewhere.}
|
9
|
+
gem.homepage = "http://github.com/zenchild/daemontor"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.extra_rdoc_files = %w(README.md)
|
13
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
14
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
15
|
+
gem.name = "daemontor"
|
16
|
+
gem.require_paths = ["lib"]
|
17
|
+
gem.version = Daemontor::VERSION
|
18
|
+
end
|
data/examples/town_crier.rb
CHANGED
@@ -2,27 +2,27 @@ $: << '../lib'
|
|
2
2
|
require 'daemontor'
|
3
3
|
|
4
4
|
class TownCrier
|
5
|
-
|
6
|
-
|
7
|
-
def initialize
|
8
|
-
$DEBUG = true # Set this so output doesn't go to the background in the example.
|
9
|
-
pid = Process.pid
|
10
|
-
daemonize!
|
11
|
-
puts "Process running in background as PID: #{Process.pid}"
|
12
|
-
cry
|
13
|
-
end
|
5
|
+
include Daemontor
|
14
6
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
7
|
+
def initialize
|
8
|
+
$DEBUG = true # Set this so output doesn't go to the background in the example.
|
9
|
+
pid = Process.pid
|
10
|
+
daemonize!
|
11
|
+
puts "Process running in background as PID: #{Process.pid}"
|
12
|
+
cry
|
13
|
+
end
|
22
14
|
|
23
|
-
|
24
|
-
|
25
|
-
|
15
|
+
def cry
|
16
|
+
loop do
|
17
|
+
puts "It's #{Time.now.to_s} and all is well"
|
18
|
+
puts "Kill the process with 'kill -INT #{Process.pid}'"
|
19
|
+
sleep 10
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def pid
|
24
|
+
return Process.pid
|
25
|
+
end
|
26
26
|
end
|
27
27
|
|
28
28
|
|
data/lib/daemontor.rb
CHANGED
@@ -1,91 +1,66 @@
|
|
1
|
-
|
2
|
-
# Copyright © 2009 Dan Wanek <dan.wanek@gmail.com>
|
3
|
-
#
|
4
|
-
#
|
5
|
-
# This file is part of Daemontor.
|
6
|
-
#
|
7
|
-
# Daemontor is free software: you can redistribute it and/or
|
8
|
-
# modify it under the terms of the GNU General Public License as published
|
9
|
-
# by the Free Software Foundation, either version 3 of the License, or (at
|
10
|
-
# your option) any later version.
|
11
|
-
#
|
12
|
-
# Daemontor 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 GNU General
|
15
|
-
# Public License for more details.
|
16
|
-
#
|
17
|
-
# You should have received a copy of the GNU General Public License along
|
18
|
-
# with Daemontor. If not, see <http://www.gnu.org/licenses/>.
|
19
|
-
#############################################################################
|
20
|
-
$:.unshift(File.dirname(__FILE__)) unless
|
21
|
-
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
1
|
+
require 'daemontor/version'
|
22
2
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
Thanks to the PickAxe book for good process handling information as well as
|
31
|
-
Travis Whitton's Daemonize module: http://grub.ath.cx/daemonize/
|
32
|
-
=end
|
3
|
+
# This module's purpose is to daemonize processes so they can be run in the
|
4
|
+
# background like a standard UNIX daemon. When Daemontor::daemonize is called
|
5
|
+
# the parent process fork()s a new child process and calls Process.detach so we
|
6
|
+
# don't have to wait for the child process to exit. The parent process then
|
7
|
+
# exits and the child process goes happily on. Since we are calling
|
8
|
+
# Process.detach we do not need to do a double-fork.
|
9
|
+
#
|
10
|
+
# Thanks to the PickAxe book for good process handling information as well as
|
11
|
+
# hints from Travis Whitton's Daemonize module: http://grub.ath.cx/daemonize/
|
33
12
|
module Daemontor
|
34
|
-
VERSION = '0.0.1'
|
35
|
-
|
36
|
-
# This is the function that makes it all happen. By default the parent process
|
37
|
-
# will be killed off. If you want to do something with the parent afterword pass a
|
38
|
-
# boolean true value and you will get access to the process back once the child is
|
39
|
-
# detached.
|
40
|
-
def daemonize!(keep_parent_alive = false)
|
41
|
-
puts "Doing fork " + Process.pid.to_s if $DEBUG
|
42
|
-
|
43
|
-
|
44
|
-
if((cpid = fork).nil?)
|
45
|
-
# Only the child processes should get here
|
46
|
-
trap("INT", proc {p_int} )
|
47
|
-
trap("QUIT", proc {p_quit} )
|
48
|
-
trap("TERM", proc {p_term} )
|
49
|
-
trap("KILL", proc {p_kill} )
|
50
|
-
unless $DEBUG
|
51
|
-
STDIN.reopen "/dev/null"
|
52
|
-
STDOUT.reopen "/dev/null", "a"
|
53
|
-
STDERR.reopen STDOUT
|
54
|
-
end
|
55
|
-
else
|
56
|
-
# Only the parent processes should get here. We detach from a specific
|
57
|
-
# PID so we don't globally detach from all PIDs. This may be handy when you need some
|
58
|
-
# children to return and some not to. The logic isn't here to do that yet, but it
|
59
|
-
# should be relatively easy to implement with this already in place.
|
60
|
-
puts "Detaching from child process #{cpid}" if $DEBUG
|
61
|
-
Process.detach(cpid)
|
62
|
-
exit unless keep_parent_alive
|
63
|
-
end
|
64
|
-
return cpid
|
65
|
-
end
|
66
13
|
|
14
|
+
# This is the function that makes it all happen. By default the parent process
|
15
|
+
# will be killed off. If you want to do something with the parent afterward
|
16
|
+
# pass a boolean true value and you will get access to the process once the
|
17
|
+
# child is detached.
|
18
|
+
def daemonize!(keep_parent_alive = false)
|
19
|
+
puts "Doing fork " + Process.pid.to_s if $DEBUG
|
20
|
+
if((cpid = fork).nil?)
|
21
|
+
# Only the child processes should get here
|
22
|
+
trap("INT", proc {p_int} )
|
23
|
+
trap("QUIT", proc {p_quit} )
|
24
|
+
trap("TERM", proc {p_term} )
|
25
|
+
trap("KILL", proc {p_kill} )
|
26
|
+
unless $DEBUG
|
27
|
+
STDIN.reopen "/dev/null"
|
28
|
+
STDOUT.reopen "/dev/null", "a"
|
29
|
+
STDERR.reopen STDOUT
|
30
|
+
end
|
31
|
+
else
|
32
|
+
# Only the parent processes should get here. We detach from a specific
|
33
|
+
# PID so we don't globally detach from all PIDs. This may be handy when you need some
|
34
|
+
# children to return and some not to. The logic isn't here to do that yet, but it
|
35
|
+
# should be relatively easy to implement with this already in place.
|
36
|
+
puts "Detaching from child process #{cpid}" if $DEBUG
|
37
|
+
Process.detach(cpid)
|
38
|
+
exit unless keep_parent_alive
|
39
|
+
end
|
40
|
+
return cpid
|
41
|
+
end
|
67
42
|
|
68
|
-
|
69
|
-
|
70
|
-
|
43
|
+
# *********************************************************************************
|
44
|
+
# You might want to overide the following methods to do something a little smarter.
|
45
|
+
# *********************************************************************************
|
71
46
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
47
|
+
def p_int
|
48
|
+
warn "Process interupt recieved. Killing process"
|
49
|
+
p_kill
|
50
|
+
end
|
76
51
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
52
|
+
def p_quit
|
53
|
+
warn "Process quit recieved. Killing process"
|
54
|
+
p_kill
|
55
|
+
end
|
81
56
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
57
|
+
def p_term
|
58
|
+
warn "Process termination recieved. Killing process"
|
59
|
+
p_kill
|
60
|
+
end
|
86
61
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
62
|
+
def p_kill
|
63
|
+
warn "Killing process #{Process.pid.to_s}"
|
64
|
+
exit
|
65
|
+
end
|
91
66
|
end
|
data/spec/daemontor_spec.rb
CHANGED
@@ -4,32 +4,32 @@ require File.dirname(__FILE__) + '/spec_helper.rb'
|
|
4
4
|
# it should serve its purpose.
|
5
5
|
describe "Test basic functionality of Daemontor" do
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
7
|
+
it "should spawn a new daemon and kill it" do
|
8
|
+
begin
|
9
|
+
master_pid = Process.pid.to_s
|
10
|
+
pids = []
|
11
|
+
puts "*** PID: #{Process.pid}"
|
12
|
+
tester = TesterClass.new
|
13
|
+
puts "****** PID: #{Process.pid}"
|
14
|
+
retval = false
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
16
|
+
if( Process.pid.to_s == master_pid )
|
17
|
+
puts "IN MASTER LOGIC: Child => #{tester.cpid}"
|
18
|
+
pids << tester.cpid.to_s
|
19
|
+
pids.each do |pid|
|
20
|
+
puts "KILLING PID: #{pid}"
|
21
|
+
Process.kill("INT", pid.to_i)
|
22
|
+
end
|
23
|
+
retval = true
|
24
|
+
else
|
25
|
+
puts "IN CHILD LOGIC"
|
26
|
+
tester.do_stuff
|
27
|
+
end
|
28
|
+
rescue ChildEnded => e
|
29
|
+
puts "Child ended appropriately"
|
30
|
+
retval = true
|
31
|
+
end
|
32
|
+
# if we get to this point lets just call it success :)
|
33
|
+
retval.should be_true
|
34
|
+
end
|
35
35
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,42 +1,33 @@
|
|
1
|
-
begin
|
2
|
-
require 'spec'
|
3
|
-
rescue LoadError
|
4
|
-
require 'rubygems' unless ENV['NO_RUBYGEMS']
|
5
|
-
gem 'rspec'
|
6
|
-
require 'spec'
|
7
|
-
end
|
8
|
-
|
9
1
|
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
10
2
|
require 'daemontor'
|
11
3
|
|
12
|
-
|
13
4
|
class TesterClass
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
5
|
+
include Daemontor
|
6
|
+
attr_reader :cpid
|
7
|
+
def initialize
|
8
|
+
$DEBUG = true # Set this so output doesn't go to the background in the example.
|
9
|
+
pid = Process.pid
|
10
|
+
@cpid = daemonize!(true)
|
11
|
+
@run = true
|
12
|
+
end
|
22
13
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
14
|
+
def do_stuff
|
15
|
+
while @run do
|
16
|
+
puts "Hello, I'm process #{Process.pid}"
|
17
|
+
sleep 15
|
18
|
+
end
|
19
|
+
end
|
29
20
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
21
|
+
def p_int
|
22
|
+
warn "Process interupt recieved. Killing process"
|
23
|
+
raise ChildEnded
|
24
|
+
exit
|
25
|
+
end
|
35
26
|
|
36
27
|
end
|
37
28
|
|
38
29
|
class ChildEnded < StandardError
|
39
|
-
|
40
|
-
|
41
|
-
|
30
|
+
def message
|
31
|
+
"Child Ended"
|
32
|
+
end
|
42
33
|
end
|