init 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,5 @@
1
+ === 1.0.0 / 2009-03-25
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
data/Manifest.txt ADDED
@@ -0,0 +1,11 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.rdoc
4
+ COPYING.txt
5
+ Rakefile
6
+ lib/init.rb
7
+ lib/init/init.rb
8
+ examples/murmur.rb
9
+ spec/init_spec.rb
10
+ spec/bin/mock_daemon.rb
11
+ spec/bin/simple_init.rb
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
@@ -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