server-starter 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/bin/start_server.rb +0 -101
- data/lib/server/starter.rb +16 -82
- data/lib/server/starter/helper.rb +3 -5
- data/lib/server/starter/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5c33bf7654cdd263ceabd3df64f6e30547a9777f
|
4
|
+
data.tar.gz: 3be2ad74bce595b12379df6990ae42e61702418a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0d579041eb87e8bb6ee920b2958bd3852e30ca94481525708d4862b5fa396533176b47bd00f6e006e15e8871f71ea4cec6929b303ca50f25fb39cbbce5c2f9c9
|
7
|
+
data.tar.gz: 04d86d76d42a50798edc7f74efa4111fe89c296ab6df6f1eff08aa25e2cc273d9a3998c55747857bb3393f6c6267e2c908bd49c83f45f39a8d85c74d63907704
|
data/CHANGELOG.md
CHANGED
data/bin/start_server.rb
CHANGED
@@ -189,104 +189,3 @@ start_server(
|
|
189
189
|
%opts,
|
190
190
|
exec => \@ARGV,
|
191
191
|
);
|
192
|
-
|
193
|
-
__END__
|
194
|
-
|
195
|
-
=head1 NAME
|
196
|
-
|
197
|
-
start_server - a superdaemon for hot-deploying server programs
|
198
|
-
|
199
|
-
=head1 SYNOPSIS
|
200
|
-
|
201
|
-
start_server [options] -- server-prog server-arg1 server-arg2 ...
|
202
|
-
|
203
|
-
# start Plack using Starlet listening at TCP port 8000
|
204
|
-
start_server --port=8000 -- plackup -s Starlet --max-workers=100 index.psgi
|
205
|
-
|
206
|
-
=head1 DESCRIPTION
|
207
|
-
|
208
|
-
This script is a frontend of L<Server::Starter>. For more information please refer to the documentation of the module.
|
209
|
-
|
210
|
-
=head1 OPTIONS
|
211
|
-
|
212
|
-
=head2 --port=(port|host:port)
|
213
|
-
|
214
|
-
TCP port to listen to (if omitted, will not bind to any ports)
|
215
|
-
|
216
|
-
=head2 --path=path
|
217
|
-
|
218
|
-
path at where to listen using unix socket (optional)
|
219
|
-
|
220
|
-
=head2 --dir=path
|
221
|
-
|
222
|
-
working directory, start_server do chdir to before exec (optional)
|
223
|
-
|
224
|
-
=head2 --interval=seconds
|
225
|
-
|
226
|
-
minimum interval to respawn the server program (default: 1)
|
227
|
-
|
228
|
-
=head2 --signal-on-hup=SIGNAL
|
229
|
-
|
230
|
-
name of the signal to be sent to the server process when start_server receives a SIGHUP (default: SIGTERM). If you use this option, be sure to also use C<--signal-on-term> below.
|
231
|
-
|
232
|
-
=head2 --signal-on-term=SIGNAL
|
233
|
-
|
234
|
-
name of the signal to be sent to the server process when start_server receives a SIGTERM (default: SIGTERM)
|
235
|
-
|
236
|
-
=head2 --pid-file=filename
|
237
|
-
|
238
|
-
if set, writes the process id of the start_server process to the file
|
239
|
-
|
240
|
-
=head2 --status-file=filename
|
241
|
-
|
242
|
-
if set, writes the status of the server process(es) to the file
|
243
|
-
|
244
|
-
=head2 --envdir=ENVDIR
|
245
|
-
|
246
|
-
directory that contains environment variables to the server processes.
|
247
|
-
It is intended for use with C<envdir> in C<daemontools>.
|
248
|
-
This can be overwritten by environment variable C<ENVDIR>.
|
249
|
-
|
250
|
-
=head2 --enable-auto-restart
|
251
|
-
|
252
|
-
enables automatic restart by time.
|
253
|
-
This can be overwritten by environment variable C<ENABLE_AUTO_RESTART>.
|
254
|
-
|
255
|
-
=head2 --auto-restart-interval=seconds
|
256
|
-
|
257
|
-
automatic restart interval (default 360). It is used with C<--enable-auto-restart> option.
|
258
|
-
This can be overwritten by environment variable C<AUTO_RESTART_INTERVAL>.
|
259
|
-
|
260
|
-
=head2 --kill-old-delay=seconds
|
261
|
-
|
262
|
-
time to suspend to send a signal to the old worker. The default value is 5 when C<--enable-auto-restart> is set, 0 otherwise.
|
263
|
-
This can be overwritten by environment variable C<KILL_OLD_DELAY>.
|
264
|
-
|
265
|
-
=head2 --restart
|
266
|
-
|
267
|
-
this is a wrapper command that reads the pid of the start_server process from --pid-file, sends SIGHUP to the process and waits until the server(s) of the older generation(s) die by monitoring the contents of the --status-file
|
268
|
-
|
269
|
-
=head2 --backlog
|
270
|
-
specifies a listen backlog parameter, whose default is SOMAXCONN (usually 128 on Linux). While SOMAXCONN is enough for most loads, large backlog is required for heavy loads.
|
271
|
-
|
272
|
-
=head2 --help
|
273
|
-
|
274
|
-
prints this help
|
275
|
-
|
276
|
-
=head2 --version
|
277
|
-
|
278
|
-
prints the version number
|
279
|
-
|
280
|
-
=head1 AUTHOR
|
281
|
-
|
282
|
-
Kazuho Oku
|
283
|
-
|
284
|
-
=head1 SEE ALSO
|
285
|
-
|
286
|
-
L<Server::Starter>
|
287
|
-
|
288
|
-
=head1 LICENSE
|
289
|
-
|
290
|
-
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
|
291
|
-
|
292
|
-
=cut
|
data/lib/server/starter.rb
CHANGED
@@ -31,7 +31,7 @@ class Server::Starter
|
|
31
31
|
ports = Array(opts[:port])
|
32
32
|
paths = Array(opts[:path])
|
33
33
|
unless ports.empty? || paths.empty?
|
34
|
-
croak "either of ``port'' or ``path'' option is
|
34
|
+
croak "either of ``port'' or ``path'' option is mandatory"
|
35
35
|
end
|
36
36
|
unless opts[:exec] && opts[:exec].is_a?(Array)
|
37
37
|
croak "mandatory option ``exec'' is missing or not an array"
|
@@ -47,7 +47,7 @@ class Server::Starter
|
|
47
47
|
if opts[:pid_file]
|
48
48
|
File.open(opts[:pid_file], "w") do |fh|
|
49
49
|
fh.puts $$
|
50
|
-
end rescue die
|
50
|
+
end rescue die "failed to open file:#{opts[:pid_file]}"
|
51
51
|
at_exit { File.unlink opts[:pid_file] rescue nil }
|
52
52
|
end
|
53
53
|
|
@@ -56,8 +56,8 @@ class Server::Starter
|
|
56
56
|
File.open(opts[:log_file], "a") do |fh|
|
57
57
|
$stdout.flush
|
58
58
|
$stderr.flush
|
59
|
-
$stdout.reopen(fh) rescue die
|
60
|
-
$stderr.reopen(fh) rescue die
|
59
|
+
$stdout.reopen(fh) rescue die "failed to reopen STDOUT to file"
|
60
|
+
$stderr.reopen(fh) rescue die "failed to reopen STDERR to file"
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
@@ -92,9 +92,9 @@ class Server::Starter
|
|
92
92
|
croak "invalid ``port'' value:#{port}"
|
93
93
|
end
|
94
94
|
rescue
|
95
|
-
die
|
95
|
+
die "failed to listen to #{port}"
|
96
96
|
end
|
97
|
-
sock.fcntl(Fcntl::F_SETFD, 0) rescue die
|
97
|
+
sock.fcntl(Fcntl::F_SETFD, 0) rescue die "fcntl(F_SETFD, 0) failed"
|
98
98
|
sockenvs.push "#{port}=#{sock.fileno}"
|
99
99
|
socks.push sock
|
100
100
|
end
|
@@ -107,7 +107,7 @@ class Server::Starter
|
|
107
107
|
paths.each do |path|
|
108
108
|
if File.symlink?(path)
|
109
109
|
warn "removing existing socket file:#{path}"
|
110
|
-
File.unlink(path) rescue die
|
110
|
+
File.unlink(path) rescue die "failed to remove existing socket file:#{path}"
|
111
111
|
end
|
112
112
|
File.unlink(path) rescue nil
|
113
113
|
saved_umask = File.umask(0)
|
@@ -115,9 +115,9 @@ class Server::Starter
|
|
115
115
|
sock = UNIXServer.new(path)
|
116
116
|
sock.listen(opts[:backlog])
|
117
117
|
rescue
|
118
|
-
die
|
118
|
+
die "failed to listen to file #{path}"
|
119
119
|
end
|
120
|
-
sock.fcntl(Fcntl::F_SETFD, 0) rescue die
|
120
|
+
sock.fcntl(Fcntl::F_SETFD, 0) rescue die "fcntl(F_SETFD, 0) failed"
|
121
121
|
sockenvs.push "path=#{sock.fileno}"
|
122
122
|
socks.push sock
|
123
123
|
end
|
@@ -144,11 +144,11 @@ class Server::Starter
|
|
144
144
|
{}
|
145
145
|
@old_workers.each {|pid, gen| gen_pids[gen] = pid }
|
146
146
|
gen_pids.keys.map(&:to_i).sort.each {|gen| tmpfh.puts "#{gen}:#{gen_pids[gen.to_s]}" }
|
147
|
-
end rescue die
|
147
|
+
end rescue die "failed to create temporary file:#{tmpfn}"
|
148
148
|
begin
|
149
149
|
File.rename(tmpfn, opts[:status_file])
|
150
150
|
rescue
|
151
|
-
die
|
151
|
+
die "failed to rename #{tmpfn} to #{opts[:status_file]}"
|
152
152
|
end
|
153
153
|
}
|
154
154
|
else
|
@@ -163,12 +163,12 @@ class Server::Starter
|
|
163
163
|
begin
|
164
164
|
pid = fork
|
165
165
|
rescue
|
166
|
-
die
|
166
|
+
die "fork(2) failed"
|
167
167
|
end
|
168
168
|
if pid.nil? # child process
|
169
169
|
args = Array(opts[:exec]).dup
|
170
170
|
if opts[:dir]
|
171
|
-
Dir.chdir opts[:dir] rescue die
|
171
|
+
Dir.chdir opts[:dir] rescue die "failed to chdir"
|
172
172
|
end
|
173
173
|
begin
|
174
174
|
bundler_with_clean_env do
|
@@ -334,7 +334,7 @@ class Server::Starter
|
|
334
334
|
line.chomp
|
335
335
|
end
|
336
336
|
rescue
|
337
|
-
die
|
337
|
+
die "failed to open file:#{opts[:pid_file]}"
|
338
338
|
end
|
339
339
|
}.call
|
340
340
|
|
@@ -345,7 +345,7 @@ class Server::Starter
|
|
345
345
|
line =~ /^(\d+):/ ? $1 : nil
|
346
346
|
end.compact.map(&:to_i).sort.uniq
|
347
347
|
rescue
|
348
|
-
die
|
348
|
+
die "failed to open file:#{opts[:status_file]}"
|
349
349
|
end
|
350
350
|
}
|
351
351
|
|
@@ -357,7 +357,7 @@ class Server::Starter
|
|
357
357
|
}.call
|
358
358
|
|
359
359
|
# send HUP
|
360
|
-
Process.kill('HUP', pid.to_i) rescue die
|
360
|
+
Process.kill('HUP', pid.to_i) rescue die "failed to send SIGHUP to the server process"
|
361
361
|
|
362
362
|
# wait for the generation
|
363
363
|
while true
|
@@ -778,69 +778,3 @@ sub _reload_env {
|
|
778
778
|
}
|
779
779
|
|
780
780
|
1;
|
781
|
-
__END__
|
782
|
-
|
783
|
-
=head1 NAME
|
784
|
-
|
785
|
-
Server::Starter - a superdaemon for hot-deploying server programs
|
786
|
-
|
787
|
-
=head1 SYNOPSIS
|
788
|
-
|
789
|
-
# from command line
|
790
|
-
% start_server --port=80 my_httpd
|
791
|
-
|
792
|
-
# in my_httpd
|
793
|
-
use Server::Starter qw(server_ports);
|
794
|
-
|
795
|
-
my $listen_sock = IO::Socket::INET->new(
|
796
|
-
Proto => 'tcp',
|
797
|
-
);
|
798
|
-
$listen_sock->fdopen((values %{server_ports()})[0], 'w')
|
799
|
-
or die "failed to bind to listening socket:$!";
|
800
|
-
|
801
|
-
while (1) {
|
802
|
-
if (my $conn = $listen_sock->accept) {
|
803
|
-
....
|
804
|
-
}
|
805
|
-
}
|
806
|
-
|
807
|
-
=head1 DESCRIPTION
|
808
|
-
|
809
|
-
It is often a pain to write a server program that supports graceful restarts, with no resource leaks. L<Server::Starter> solves the problem by splitting the task into two. One is L<start_server>, a script provided as a part of the module, which works as a superdaemon that binds to zero or more TCP ports or unix sockets, and repeatedly spawns the server program that actually handles the necessary tasks (for example, responding to incoming commenctions). The spawned server programs under L<Server::Starter> call accept(2) and handle the requests.
|
810
|
-
|
811
|
-
To gracefully restart the server program, send SIGHUP to the superdaemon. The superdaemon spawns a new server program, and if (and only if) it starts up successfully, sends SIGTERM to the old server program.
|
812
|
-
|
813
|
-
By using L<Server::Starter> it is much easier to write a hot-deployable server. Following are the only requirements a server program to be run under L<Server::Starter> should conform to:
|
814
|
-
|
815
|
-
- receive file descriptors to listen to through an environment variable
|
816
|
-
- perform a graceful shutdown when receiving SIGTERM
|
817
|
-
|
818
|
-
A Net::Server personality that can be run under L<Server::Starter> exists under the name L<Net::Server::SS::PreFork>.
|
819
|
-
|
820
|
-
=head1 METHODS
|
821
|
-
|
822
|
-
=over 4
|
823
|
-
|
824
|
-
=item server_ports
|
825
|
-
|
826
|
-
Returns zero or more file descriptors on which the server program should call accept(2) in a hashref. Each element of the hashref is: (host:port|port|path_of_unix_socket) => file_descriptor.
|
827
|
-
|
828
|
-
=item start_server
|
829
|
-
|
830
|
-
Starts the superdaemon. Used by the C<start_server> script.
|
831
|
-
|
832
|
-
=back
|
833
|
-
|
834
|
-
=head1 AUTHOR
|
835
|
-
|
836
|
-
Kazuho Oku
|
837
|
-
|
838
|
-
=head1 SEE ALSO
|
839
|
-
|
840
|
-
L<Net::Server::SS::PreFork>
|
841
|
-
|
842
|
-
=head1 LICENSE
|
843
|
-
|
844
|
-
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
|
845
|
-
|
846
|
-
=cut
|
@@ -10,12 +10,10 @@ class Server
|
|
10
10
|
exit 1
|
11
11
|
end
|
12
12
|
|
13
|
-
def die(
|
14
|
-
if
|
15
|
-
|
16
|
-
$stderr.puts "#{msg}:#{e.class} #{e.message}"
|
13
|
+
def die(msg)
|
14
|
+
if $!
|
15
|
+
$stderr.puts "#{msg}:#{$!.class} #{$!.message}"
|
17
16
|
else
|
18
|
-
msg = args[0]
|
19
17
|
$stderr.puts msg
|
20
18
|
end
|
21
19
|
exit 1
|