init 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/COPYING.txt +674 -0
- data/History.txt +5 -0
- data/Manifest.txt +11 -0
- data/README.rdoc +164 -0
- data/Rakefile +19 -0
- data/examples/murmur.rb +51 -0
- data/lib/init.rb +30 -0
- data/lib/init/init.rb +85 -0
- data/spec/bin/mock_daemon.rb +32 -0
- data/spec/bin/simple_init.rb +86 -0
- data/spec/init_spec.rb +129 -0
- metadata +121 -0
- metadata.gz.sig +0 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
= Init
|
2
|
+
|
3
|
+
* Project: https://rubyforge.org/projects/aef/
|
4
|
+
* RDoc: http://aef.rubyforge.org/init/
|
5
|
+
* Github: http://github.com/aef/init/
|
6
|
+
|
7
|
+
== DESCRIPTION:
|
8
|
+
|
9
|
+
Clean and simple *nix init scripts with Ruby
|
10
|
+
|
11
|
+
== FEATURES/PROBLEMS:
|
12
|
+
|
13
|
+
* Tested and fully working on:
|
14
|
+
* Ubuntu Linux 8.10 i386_64 (Ruby 1.8.7 and 1.9.1p0)
|
15
|
+
* Debian GNU/Linux 4.0 i386 (Ruby 1.8.6)
|
16
|
+
|
17
|
+
== SYNOPSIS:
|
18
|
+
|
19
|
+
Simply subclass Init and define at least a start and a stop method. At the end,
|
20
|
+
call the parse method on that class.
|
21
|
+
|
22
|
+
class DemoSubclass < Aef::Init
|
23
|
+
def start
|
24
|
+
system('echo start')
|
25
|
+
end
|
26
|
+
|
27
|
+
def stop
|
28
|
+
system('echo stop')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
DemoSubclass.parse
|
33
|
+
|
34
|
+
To be able to call the commands from ruby you should wrap the parse method call
|
35
|
+
in a block that only calls it if the script is executed on the commandline.
|
36
|
+
|
37
|
+
if __FILE__ == $PROGRAM_NAME
|
38
|
+
DemoSubclass.parse
|
39
|
+
end
|
40
|
+
|
41
|
+
There is no need to implement the command restart in most cases, as there is one
|
42
|
+
defined by default, which simply calls the commands stop and start in a row.
|
43
|
+
A delay can between the two commands can be defined:
|
44
|
+
|
45
|
+
class DemoSubclass < Aef::Init
|
46
|
+
...
|
47
|
+
stop_start_delay 3
|
48
|
+
...
|
49
|
+
end
|
50
|
+
|
51
|
+
If no command is specified on the commandline, restart is called by default.
|
52
|
+
This default can be changed:
|
53
|
+
|
54
|
+
class DemoSubclass < Aef::Init
|
55
|
+
...
|
56
|
+
default_command :start
|
57
|
+
...
|
58
|
+
end
|
59
|
+
|
60
|
+
If you want to share commands between init scripts, you can also simple put a
|
61
|
+
class between Init and the final implementation:
|
62
|
+
|
63
|
+
class CommonCommands > Aef::Init
|
64
|
+
def common
|
65
|
+
system('echo common')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class DemoSubclass > CommonCommands
|
70
|
+
...
|
71
|
+
end
|
72
|
+
|
73
|
+
See examples/murmur.rb and spec/bin/simple_ini.rb for working example classes.
|
74
|
+
|
75
|
+
== REQUIREMENTS:
|
76
|
+
|
77
|
+
* rubygems
|
78
|
+
|
79
|
+
=== Additional for automated testing
|
80
|
+
* hoe
|
81
|
+
* rspec
|
82
|
+
* sys-uname
|
83
|
+
|
84
|
+
== INSTALL:
|
85
|
+
|
86
|
+
=== Normal
|
87
|
+
|
88
|
+
gem install init
|
89
|
+
|
90
|
+
=== High security (recommended)
|
91
|
+
|
92
|
+
There is a high security installation option available through rubygems. It is
|
93
|
+
highly recommended over the normal installation, although it may be a bit less
|
94
|
+
comfortable. To use the installation method, you will need my public key, which
|
95
|
+
I use for cryptographic signatures on all my gems. You can find the public key
|
96
|
+
and more detailed verification information in the aef-certificates section of my
|
97
|
+
rubyforge project[https://rubyforge.org/frs/?group_id=7890&release_id=31749]
|
98
|
+
|
99
|
+
Add the key to your rubygems' trusted certificates by the following command:
|
100
|
+
|
101
|
+
gem cert --add aef.pem
|
102
|
+
|
103
|
+
Now you can install the gem while automatically verifying it's signature by the
|
104
|
+
following command:
|
105
|
+
|
106
|
+
gem install init --ignore-dependencies -P HighSecurity
|
107
|
+
|
108
|
+
Please notice that you will need other keys for dependent libraries, so you may
|
109
|
+
have to install dependencies manually.
|
110
|
+
|
111
|
+
=== Automated testing
|
112
|
+
|
113
|
+
You can test this package through rspec on your system. First find the path
|
114
|
+
where the gem was installed to:
|
115
|
+
|
116
|
+
gem which init
|
117
|
+
|
118
|
+
Go into the root directory of the installed gem and run the following command
|
119
|
+
to start the test runner:
|
120
|
+
|
121
|
+
rake spec
|
122
|
+
|
123
|
+
On Windows systems you have to run the following instead:
|
124
|
+
|
125
|
+
spec spec/**/*_spec.rb
|
126
|
+
|
127
|
+
If something goes wrong you should be noticed through failing examples.
|
128
|
+
|
129
|
+
== DEVELOPMENT:
|
130
|
+
|
131
|
+
This software is developed in the source code management system git hosted
|
132
|
+
at github.com. You can download the most recent sourcecode through the following
|
133
|
+
command:
|
134
|
+
|
135
|
+
git clone git://github.com/aef/init.git
|
136
|
+
|
137
|
+
Help on making this software better is always very appreciated. If you want your
|
138
|
+
changes to be included in the official release, please send me a patch through
|
139
|
+
the project's tracker[https://rubyforge.org/tracker/?group_id=7890] at
|
140
|
+
rubyforge.org. You can generate a patch-file by the following command:
|
141
|
+
|
142
|
+
git diff > patch.diff
|
143
|
+
|
144
|
+
Please make sure to write tests for your changes and notice that I can't promise
|
145
|
+
to include your changes before reviewing them.
|
146
|
+
|
147
|
+
== LICENSE:
|
148
|
+
|
149
|
+
Copyright 2009 Alexander E. Fischer <aef@raxys.net>
|
150
|
+
|
151
|
+
This file is part of Init.
|
152
|
+
|
153
|
+
Init is free software: you can redistribute it and/or modify
|
154
|
+
it under the terms of the GNU General Public License as published by
|
155
|
+
the Free Software Foundation, either version 3 of the License, or
|
156
|
+
(at your option) any later version.
|
157
|
+
|
158
|
+
This program is distributed in the hope that it will be useful,
|
159
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
160
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
161
|
+
GNU General Public License for more details.
|
162
|
+
|
163
|
+
You should have received a copy of the GNU General Public License
|
164
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hoe'
|
5
|
+
require './lib/init.rb'
|
6
|
+
|
7
|
+
Hoe.new('init', Aef::Init::VERSION) do |p|
|
8
|
+
p.rubyforge_name = 'aef'
|
9
|
+
p.developer('Alexander E. Fischer', 'aef@raxys.net')
|
10
|
+
p.extra_dev_deps = %w{rspec facets}
|
11
|
+
p.url = 'https://rubyforge.org/projects/aef/'
|
12
|
+
p.readme_file = 'README.rdoc'
|
13
|
+
p.extra_rdoc_files = %w{README.rdoc}
|
14
|
+
p.spec_extras = {
|
15
|
+
:rdoc_options => ['--main', 'README.rdoc', '--inline-source', '--line-numbers', '--title', 'Init']
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
# vim: syntax=Ruby
|
data/examples/murmur.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Copyright 2009 Alexander E. Fischer <aef@raxys.net>
|
4
|
+
#
|
5
|
+
# This file is part of Init.
|
6
|
+
#
|
7
|
+
# Init is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
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
|
18
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
require 'init'
|
21
|
+
|
22
|
+
# An example init script for the voice chat application Murmur
|
23
|
+
class Murmur < Aef::Init
|
24
|
+
PATH = '/opt/murmur'
|
25
|
+
DAEMON = File.join(PATH, 'murmur.x86')
|
26
|
+
PIDFILE = '/var/run/murmur/murmur.pid'
|
27
|
+
USER = 'mumble'
|
28
|
+
|
29
|
+
# Defines the seconds to wait between stop and start in the predefined restart
|
30
|
+
# command
|
31
|
+
stop_start_delay 1
|
32
|
+
|
33
|
+
# If not set this defaults to :restart
|
34
|
+
default_command :start
|
35
|
+
|
36
|
+
# An implementation of the start method for the mumble daemon
|
37
|
+
def start
|
38
|
+
system("start-stop-daemon --start --chdir #{PATH} --chuid #{USER} --exec #{DAEMON}")
|
39
|
+
end
|
40
|
+
|
41
|
+
# An implementation of the stop method for the mumble daemon
|
42
|
+
def stop
|
43
|
+
system("start-stop-daemon --stop --pidfile #{PIDFILE}")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# The parser is only executed if the script is executed as a program, never
|
48
|
+
# when the script is required in a ruby program
|
49
|
+
if __FILE__ == $PROGRAM_NAME
|
50
|
+
Murmur.parse
|
51
|
+
end
|
data/lib/init.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# Copyright 2009 Alexander E. Fischer <aef@raxys.net>
|
2
|
+
#
|
3
|
+
# This file is part of Init.
|
4
|
+
#
|
5
|
+
# Init is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
# Namespace for projects of Alexander E. Fischer <aef@raxys.net>
|
19
|
+
#
|
20
|
+
# If you want to be able to simply type Example instead of Aef::Example to
|
21
|
+
# address classes in this namespace simply write the following before using the
|
22
|
+
# classes:
|
23
|
+
#
|
24
|
+
# include Aef
|
25
|
+
module Aef
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
libdir = File.dirname(__FILE__)
|
30
|
+
require File.join(libdir, 'init/init')
|
data/lib/init/init.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# Copyright 2009 Alexander E. Fischer <aef@raxys.net>
|
2
|
+
#
|
3
|
+
# This file is part of Init.
|
4
|
+
#
|
5
|
+
# Init is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
require 'rubygems'
|
19
|
+
|
20
|
+
# Clean and simple *nix init scripts with Ruby
|
21
|
+
class Aef::Init
|
22
|
+
VERSION = '1.0.0'
|
23
|
+
|
24
|
+
# Call this to begin commandline parsing
|
25
|
+
#
|
26
|
+
# If an invalid command is specified on the commandline, a usage example is
|
27
|
+
# displayed. If no command is specified, the default command is started
|
28
|
+
def self.parse
|
29
|
+
command = ARGV.shift || :default
|
30
|
+
|
31
|
+
valid_commands = []
|
32
|
+
|
33
|
+
self.ancestors.each do |klass|
|
34
|
+
valid_commands += klass.public_instance_methods(false)
|
35
|
+
break if klass == Aef::Init
|
36
|
+
end
|
37
|
+
|
38
|
+
valid_commands.uniq!
|
39
|
+
|
40
|
+
@@default_command ||= 'restart'
|
41
|
+
@@stop_start_delay ||= 0
|
42
|
+
|
43
|
+
# This is neccessary because since ruby 1.9, the instance_methods method
|
44
|
+
# returns an array of symbols instead of an array of strings which it did
|
45
|
+
# in 1.8
|
46
|
+
command = command.to_sym if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('1.9')
|
47
|
+
|
48
|
+
if command == :default
|
49
|
+
new.send(@@default_command)
|
50
|
+
elsif valid_commands.include?(command)
|
51
|
+
new.send(command)
|
52
|
+
else
|
53
|
+
puts "Usage: #$PROGRAM_NAME {#{valid_commands.sort.join('|')}}"; exit false
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Set a delay in seconds between the call of the stop and the start method in
|
58
|
+
# the predefined restart method
|
59
|
+
def self.stop_start_delay(seconds)
|
60
|
+
@@stop_start_delay = seconds
|
61
|
+
end
|
62
|
+
|
63
|
+
# Set a default command to be called if no command is specified on the
|
64
|
+
# commandline.
|
65
|
+
def self.default_command(command)
|
66
|
+
@@default_command = command
|
67
|
+
end
|
68
|
+
|
69
|
+
# The start method needs to be implemented in a subclass
|
70
|
+
def start
|
71
|
+
warn 'start method needs to be implemented'; exit false
|
72
|
+
end
|
73
|
+
|
74
|
+
# The stop method needs to be implemented in a subclass
|
75
|
+
def stop
|
76
|
+
warn 'stop method needs to be implemented'; exit false
|
77
|
+
end
|
78
|
+
|
79
|
+
# By default restart simply calls stop and then start
|
80
|
+
def restart
|
81
|
+
stop
|
82
|
+
sleep @@stop_start_delay
|
83
|
+
start
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Copyright 2009 Alexander E. Fischer <aef@raxys.net>
|
4
|
+
#
|
5
|
+
# This file is part of Init.
|
6
|
+
#
|
7
|
+
# Init is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
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
|
18
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
# This is a simple mock daemon which will write all commandline arguments it
|
21
|
+
# recevies to a file specified as first commandline option
|
22
|
+
|
23
|
+
if ARGV.empty?
|
24
|
+
puts "Usage: #$PROGRAM_NAME output_file [arguments]"
|
25
|
+
else
|
26
|
+
puts arguments = ARGV.join(' ')
|
27
|
+
puts output_file = ARGV.first
|
28
|
+
|
29
|
+
File.open(output_file, 'a') do |f|
|
30
|
+
f.puts(arguments)
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Copyright 2009 Alexander E. Fischer <aef@raxys.net>
|
4
|
+
#
|
5
|
+
# This file is part of Init.
|
6
|
+
#
|
7
|
+
# Init is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
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
|
18
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
require 'lib/init'
|
21
|
+
|
22
|
+
# A library in between the base and the final class
|
23
|
+
class MiddleInit < Aef::Init
|
24
|
+
RUBY_PATH = 'ruby'
|
25
|
+
MOCK_EXECUTABLE = "#{RUBY_PATH} spec/bin/mock_daemon.rb"
|
26
|
+
|
27
|
+
def middle
|
28
|
+
tempfile = ARGV.first
|
29
|
+
system("#{MOCK_EXECUTABLE} #{tempfile} --middle -e --abc")
|
30
|
+
end
|
31
|
+
|
32
|
+
protected
|
33
|
+
|
34
|
+
def middle_protected
|
35
|
+
warn 'This should not be executable as a command'; exit false
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def middle_private
|
41
|
+
warn 'This should not be executable as a command'; exit false
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# The final implementation
|
46
|
+
class SimpleInit < MiddleInit
|
47
|
+
RUBY_PATH = 'ruby'
|
48
|
+
MOCK_EXECUTABLE = "#{RUBY_PATH} spec/bin/mock_daemon.rb"
|
49
|
+
|
50
|
+
# Defines the seconds to wait between stop and start in the predefined restart
|
51
|
+
# command
|
52
|
+
stop_start_delay 1.5
|
53
|
+
|
54
|
+
# If not set this defaults to :restart
|
55
|
+
default_command :stop
|
56
|
+
|
57
|
+
# An implementation of the start method for the mumble daemon
|
58
|
+
def start
|
59
|
+
tempfile = ARGV.first
|
60
|
+
system("#{MOCK_EXECUTABLE} #{tempfile} --start --example -y")
|
61
|
+
end
|
62
|
+
|
63
|
+
# An implementation of the stop method for the mumble daemon
|
64
|
+
def stop
|
65
|
+
tempfile = ARGV.first
|
66
|
+
system("#{MOCK_EXECUTABLE} #{tempfile} --stop --example -y")
|
67
|
+
end
|
68
|
+
|
69
|
+
protected
|
70
|
+
|
71
|
+
def end_protected
|
72
|
+
warn 'This should not be executable as a command'; exit false
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def end_private
|
78
|
+
warn 'This should not be executable as a command'; exit false
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# The parser is only executed if the script is executed as a program, never
|
83
|
+
# when the script is required in a ruby program
|
84
|
+
if __FILE__ == $PROGRAM_NAME
|
85
|
+
SimpleInit.parse
|
86
|
+
end
|