zbatery 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +6 -0
- data/.gitignore +18 -0
- data/.manifest +21 -0
- data/COPYING +339 -0
- data/ChangeLog +35 -0
- data/Documentation/.gitignore +5 -0
- data/Documentation/GNUmakefile +30 -0
- data/Documentation/zbatery.1.txt +154 -0
- data/GIT-VERSION-FILE +1 -0
- data/GIT-VERSION-GEN +40 -0
- data/GNUmakefile +169 -0
- data/LICENSE +55 -0
- data/NEWS +4 -0
- data/README +130 -0
- data/Rakefile +158 -0
- data/bin/zbatery +166 -0
- data/lib/zbatery.rb +154 -0
- data/local.mk.sample +78 -0
- data/man/man1/zbatery.1 +187 -0
- data/setup.rb +1586 -0
- data/zbatery.gemspec +55 -0
- metadata +97 -0
data/lib/zbatery.rb
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
require 'rainbows'
|
3
|
+
|
4
|
+
module Zbatery
|
5
|
+
|
6
|
+
# current version of Zbatery
|
7
|
+
VERSION = "0.0.0"
|
8
|
+
|
9
|
+
class << self
|
10
|
+
|
11
|
+
# runs the Zbatery HttpServer with +app+ and +options+ and does
|
12
|
+
# not return until the server has exited.
|
13
|
+
def run(app, options = {})
|
14
|
+
HttpServer.new(app, options).start.join
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
Rainbows::Const::RACK_DEFAULTS["SERVER_SOFTWARE"] = "Zbatery #{VERSION}"
|
19
|
+
|
20
|
+
# true if our Ruby implementation supports unlinked files
|
21
|
+
UnlinkedIO = begin
|
22
|
+
tmp = Unicorn::Util.tmpio
|
23
|
+
tmp.chmod(0)
|
24
|
+
tmp.close
|
25
|
+
true
|
26
|
+
rescue
|
27
|
+
false
|
28
|
+
end
|
29
|
+
|
30
|
+
# we don't actually fork workers, but allow using the
|
31
|
+
# {before,after}_fork hooks found in Unicorn/Rainbows!
|
32
|
+
# config files...
|
33
|
+
FORK_HOOK = lambda { |_,_| }
|
34
|
+
|
35
|
+
class HttpServer < Rainbows::HttpServer
|
36
|
+
|
37
|
+
# only used if no concurrency model is specified
|
38
|
+
def worker_loop(worker)
|
39
|
+
init_worker_process(worker)
|
40
|
+
begin
|
41
|
+
ret = IO.select(LISTENERS, nil, nil, nil) and
|
42
|
+
ret.first.each do |sock|
|
43
|
+
begin
|
44
|
+
process_client(sock.accept_nonblock)
|
45
|
+
rescue Errno::EAGAIN, Errno::ECONNABORTED
|
46
|
+
end
|
47
|
+
end
|
48
|
+
rescue Errno::EINTR
|
49
|
+
rescue Errno::EBADF, TypeError
|
50
|
+
break
|
51
|
+
rescue => e
|
52
|
+
Rainbows::Error.listen_loop(e)
|
53
|
+
end while G.alive
|
54
|
+
end
|
55
|
+
|
56
|
+
# no-op
|
57
|
+
def maintain_worker_count; end
|
58
|
+
|
59
|
+
# can't just do a graceful exit if reopening logs fails, so we just
|
60
|
+
# continue on...
|
61
|
+
def reopen_logs
|
62
|
+
logger.info "reopening logs"
|
63
|
+
Unicorn::Util.reopen_logs
|
64
|
+
logger.info "done reopening logs"
|
65
|
+
rescue => e
|
66
|
+
logger.error "failed reopening logs #{e.message}"
|
67
|
+
end
|
68
|
+
|
69
|
+
def join
|
70
|
+
begin
|
71
|
+
trap(:INT) { stop(false) } # Mongrel trapped INT for Win32...
|
72
|
+
|
73
|
+
# try these anyways regardless of platform...
|
74
|
+
trap(:TERM) { stop(false) }
|
75
|
+
trap(:QUIT) { stop }
|
76
|
+
trap(:USR1) { reopen_logs }
|
77
|
+
trap(:USR2) { reexec }
|
78
|
+
|
79
|
+
# no other way to reliably switch concurrency models...
|
80
|
+
trap(:HUP) { reexec; stop }
|
81
|
+
|
82
|
+
# technically feasible in some cases, just not sanely supportable:
|
83
|
+
%w(TTIN TTOU WINCH).each do |sig|
|
84
|
+
trap(sig) { logger.info "SIG#{sig} is not handled by Zbatery" }
|
85
|
+
end
|
86
|
+
rescue => e # hopefully ignores errors on Win32...
|
87
|
+
logger.error "failed to setup signal handler: #{e.message}"
|
88
|
+
end
|
89
|
+
worker = Worker.new(0, $stdout)
|
90
|
+
before_fork.call(self, worker)
|
91
|
+
worker_loop(worker) # runs forever
|
92
|
+
end
|
93
|
+
|
94
|
+
def stop(graceful = true)
|
95
|
+
Rainbows::G.quit!
|
96
|
+
exit!(0) unless graceful
|
97
|
+
end
|
98
|
+
|
99
|
+
def before_fork
|
100
|
+
hook = super
|
101
|
+
hook == FORK_HOOK or
|
102
|
+
logger.warn "calling before_fork without forking"
|
103
|
+
hook
|
104
|
+
end
|
105
|
+
|
106
|
+
def after_fork
|
107
|
+
hook = super
|
108
|
+
hook == FORK_HOOK or
|
109
|
+
logger.warn "calling after_fork without having forked"
|
110
|
+
hook
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# :stopdoc:
|
116
|
+
# override stuff we don't need or can't use portably
|
117
|
+
module Rainbows
|
118
|
+
|
119
|
+
module Base
|
120
|
+
# master == worker in our case
|
121
|
+
def init_worker_process(worker)
|
122
|
+
after_fork.call(self, worker)
|
123
|
+
build_app! unless preload_app
|
124
|
+
logger.info "Zbatery #@use worker_connections=#@worker_connections"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# we can't/don't need to do the fchmod heartbeat Unicorn/Rainbows! does
|
129
|
+
def G.tick
|
130
|
+
alive
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
module Unicorn
|
135
|
+
|
136
|
+
class Configurator
|
137
|
+
DEFAULTS[:before_fork] = DEFAULTS[:after_fork] = Zbatery::FORK_HOOK
|
138
|
+
end
|
139
|
+
|
140
|
+
unless Zbatery::UnlinkedIO
|
141
|
+
require 'tempfile'
|
142
|
+
class Util
|
143
|
+
|
144
|
+
# Tempfiles should get automatically unlinked by GC
|
145
|
+
def self.tmpio
|
146
|
+
fp = Tempfile.new("zbatery")
|
147
|
+
fp.binmode
|
148
|
+
fp.sync = true
|
149
|
+
fp
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
data/local.mk.sample
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
|
2
|
+
# this is the local.mk file used by Eric Wong on his dev boxes.
|
3
|
+
# GNUmakefile will source local.mk in the top-level source tree
|
4
|
+
# if it is present.
|
5
|
+
#
|
6
|
+
# This is depends on a bunch of GNU-isms from bash, sed, touch.
|
7
|
+
|
8
|
+
RSYNC = rsync
|
9
|
+
DLEXT := so
|
10
|
+
gems := rack-1.0.1
|
11
|
+
# gems += unicorn-0.95.2 # installed via setup.rb
|
12
|
+
# gems += rainbows-0.8.0 # installed via setup.rb
|
13
|
+
gems += rev-0.3.1
|
14
|
+
gems += iobuffer-0.1.1
|
15
|
+
gems += eventmachine-0.12.10
|
16
|
+
gems += async_sinatra-0.1.5 sinatra-0.9.4
|
17
|
+
|
18
|
+
# Avoid loading rubygems to speed up tests because gmake is
|
19
|
+
# fork+exec heavy with Ruby.
|
20
|
+
prefix = $(HOME)
|
21
|
+
ifeq ($(r19),)
|
22
|
+
RUBY := $(prefix)/bin/ruby
|
23
|
+
gem_paths := $(addprefix $(prefix)/lib/ruby/gems/1.8/gems/,$(gems))
|
24
|
+
else
|
25
|
+
prefix := $(prefix)/ruby-1.9
|
26
|
+
export PATH := $(prefix)/bin:$(PATH)
|
27
|
+
RUBY := $(prefix)/bin/ruby --disable-gems
|
28
|
+
gems += case-0.5 revactor-0.1.5
|
29
|
+
gem_paths := $(addprefix $(prefix)/lib/ruby/gems/1.9.1/gems/,$(gems))
|
30
|
+
endif
|
31
|
+
|
32
|
+
ifdef gem_paths
|
33
|
+
sp :=
|
34
|
+
sp +=
|
35
|
+
export RUBYLIB := $(subst $(sp),:,$(addsuffix /lib,$(gem_paths)))
|
36
|
+
endif
|
37
|
+
|
38
|
+
# pipefail is THE reason to use bash (v3+) or never revisions of ksh93
|
39
|
+
# SHELL := /bin/bash -e -o pipefail
|
40
|
+
SHELL := /bin/ksh93 -e -o pipefail
|
41
|
+
|
42
|
+
# trace execution of tests
|
43
|
+
# TRACER = strace -f -o $(t_pfx).strace -s 100000
|
44
|
+
TRACER = /usr/bin/time -v -o $(t_pfx).time
|
45
|
+
|
46
|
+
full-test: test-18 test-19
|
47
|
+
test-18:
|
48
|
+
$(MAKE) test 2>&1 | sed -e 's!^!1.8 !'
|
49
|
+
test-19:
|
50
|
+
$(MAKE) test r19=t 2>&1 | sed -e 's!^!1.9 !'
|
51
|
+
|
52
|
+
latest: NEWS
|
53
|
+
@awk 'BEGIN{RS="=== ";ORS=""}NR==2{sub(/\n$$/,"");print RS""$$0 }' < $<
|
54
|
+
|
55
|
+
# publishes docs to http://zbatery.bogomip.org/
|
56
|
+
publish_doc:
|
57
|
+
-git set-file-times
|
58
|
+
$(RM) -r doc ChangeLog NEWS
|
59
|
+
$(MAKE) doc LOG_VERSION=$(shell git tag -l | tail -1)
|
60
|
+
$(MAKE) -s latest > doc/LATEST
|
61
|
+
find doc/images doc/js -type f | \
|
62
|
+
TZ=UTC xargs touch -d '1970-01-01 00:00:00' doc/rdoc.css
|
63
|
+
$(MAKE) doc_gz
|
64
|
+
chmod 644 $$(find doc -type f)
|
65
|
+
$(RSYNC) -av doc/ dcvr:/srv/zbatery/
|
66
|
+
git ls-files | xargs touch
|
67
|
+
|
68
|
+
# Create gzip variants of the same timestamp as the original so nginx
|
69
|
+
# "gzip_static on" can serve the gzipped versions directly.
|
70
|
+
doc_gz: docs = $(shell find doc -type f ! -regex '^.*\.\(gif\|jpg\|png\|gz\)$$')
|
71
|
+
doc_gz:
|
72
|
+
touch doc/NEWS.atom.xml -d "$$(awk 'NR==1{print $$4,$$5,$$6}' NEWS)"
|
73
|
+
for i in $(docs); do \
|
74
|
+
gzip --rsyncable -9 < $$i > $$i.gz; touch -r $$i $$i.gz; done
|
75
|
+
|
76
|
+
# launches any of the following shells with RUBYLIB set
|
77
|
+
irb sh bash ksh:
|
78
|
+
$@
|
data/man/man1/zbatery.1
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
.TH zbatery 1 "December 9, 2009" "Zbatery User Manual"
|
2
|
+
.SH NAME
|
3
|
+
.PP
|
4
|
+
zbatery - rackup-like command to launch Zbatery
|
5
|
+
.SH SYNOPSIS
|
6
|
+
.PP
|
7
|
+
zbatery [-c CONFIG_FILE] [-E RACK_ENV] [-D] [RACKUP_FILE]
|
8
|
+
.SH DESCRIPTION
|
9
|
+
.PP
|
10
|
+
A rackup(1)-like command to launch Rack applications using Zbatery.
|
11
|
+
It is expected to be started in your application root (APP_ROOT),
|
12
|
+
but \[lq]Dir.chdir\[rq] may also be executed in the CONFIG_FILE or
|
13
|
+
RACKUP_FILE.
|
14
|
+
.PP
|
15
|
+
While Zbatery takes a myriad of command-line options for
|
16
|
+
compatibility with ruby(1) and rackup(1), it is recommended to
|
17
|
+
stick to the few command-line options specified in the SYNOPSIS and
|
18
|
+
use the CONFIG_FILE as much as possible.
|
19
|
+
.SH RACKUP FILE
|
20
|
+
.PP
|
21
|
+
This defaults to "config.ru" in APP_ROOT.
|
22
|
+
It should be the same file used by rackup(1) and other Rack
|
23
|
+
launchers, it uses the \f[I]Rack::Builder\f[] DSL.
|
24
|
+
.PP
|
25
|
+
Embedded command-line options are mostly parsed for compatibility
|
26
|
+
with rackup(1) but strongly discouraged.
|
27
|
+
.SH UNICORN OPTIONS
|
28
|
+
.TP
|
29
|
+
.B -c, --config-file CONFIG_FILE
|
30
|
+
Path to the Unicorn-specific config file.
|
31
|
+
The config file is implemented as a Ruby DSL, so Ruby code may
|
32
|
+
executed (e.g.
|
33
|
+
\[lq]Dir.chdir\[rq], \[lq]Process::UID.change_privilege\[rq]).
|
34
|
+
See the RDoc/ri for the \f[I]Unicorn::Configurator\f[] class for
|
35
|
+
the full list of directives available from the DSL.
|
36
|
+
.RS
|
37
|
+
.RE
|
38
|
+
.TP
|
39
|
+
.B -D, --daemonize
|
40
|
+
Run daemonized in the background.
|
41
|
+
The process is detached from the controlling terminal and stdin is
|
42
|
+
redirected to \[lq]/dev/null\[rq].
|
43
|
+
Unlike many common UNIX daemons, we do not chdir to "/" upon
|
44
|
+
daemonization to allow more control over the startup/upgrade
|
45
|
+
process.
|
46
|
+
Unless specified in the CONFIG_FILE, stderr and stdout will also be
|
47
|
+
redirected to \[lq]/dev/null\[rq].
|
48
|
+
.RS
|
49
|
+
.RE
|
50
|
+
.TP
|
51
|
+
.B -E, --env RACK_ENV
|
52
|
+
Run under the given RACK_ENV.
|
53
|
+
See the RACK ENVIRONMENT section for more details.
|
54
|
+
.RS
|
55
|
+
.RE
|
56
|
+
.TP
|
57
|
+
.B -l, --listen ADDRESS
|
58
|
+
Listens on a given ADDRESS.
|
59
|
+
ADDRESS may be in the form of HOST:PORT or PATH, HOST:PORT is taken
|
60
|
+
to mean a TCP socket and PATH is meant to be a path to a UNIX
|
61
|
+
domain socket.
|
62
|
+
Defaults to \[lq]0.0.0.0:8080\[rq] (all addresses on TCP port 8080)
|
63
|
+
For production deployments, specifying the \[lq]listen\[rq]
|
64
|
+
directive in CONFIG_FILE is recommended as it allows fine-tuning of
|
65
|
+
socket options.
|
66
|
+
.RS
|
67
|
+
.RE
|
68
|
+
.SH RACKUP COMPATIBILITY OPTIONS
|
69
|
+
.TP
|
70
|
+
.B -o, --host HOST
|
71
|
+
Listen on a TCP socket belonging to HOST, default is
|
72
|
+
\[lq]0.0.0.0\[rq] (all addresses).
|
73
|
+
If specified multiple times on the command-line, only the
|
74
|
+
last-specified value takes effect.
|
75
|
+
This option only exists for compatibility with the rackup(1)
|
76
|
+
command, use of \[lq]-l\[rq]/\[lq]--listen\[rq] switch is
|
77
|
+
recommended instead.
|
78
|
+
.RS
|
79
|
+
.RE
|
80
|
+
.TP
|
81
|
+
.B -p, --port PORT
|
82
|
+
Listen on the specified TCP PORT, default is 8080.
|
83
|
+
If specified multiple times on the command-line, only the
|
84
|
+
last-specified value takes effect.
|
85
|
+
This option only exists for compatibility with the rackup(1)
|
86
|
+
command, use of \[lq]-l\[rq]/\[lq]--listen\[rq] switch is
|
87
|
+
recommended instead.
|
88
|
+
.RS
|
89
|
+
.RE
|
90
|
+
.TP
|
91
|
+
.B -s, --server SERVER
|
92
|
+
No-op, this exists only for compatibility with rackup(1).
|
93
|
+
.RS
|
94
|
+
.RE
|
95
|
+
.SH RUBY OPTIONS
|
96
|
+
.TP
|
97
|
+
.B -e, --eval LINE
|
98
|
+
Evaluate a LINE of Ruby code.
|
99
|
+
This evaluation happens immediately as the command-line is being
|
100
|
+
parsed.
|
101
|
+
.RS
|
102
|
+
.RE
|
103
|
+
.TP
|
104
|
+
.B -d, --debug
|
105
|
+
Turn on debug mode, the $DEBUG variable is set to true.
|
106
|
+
.RS
|
107
|
+
.RE
|
108
|
+
.TP
|
109
|
+
.B -w, --warn
|
110
|
+
Turn on verbose warnings, the $VERBOSE variable is set to true.
|
111
|
+
.RS
|
112
|
+
.RE
|
113
|
+
.TP
|
114
|
+
.B -I, --include PATH
|
115
|
+
specify $LOAD_PATH.
|
116
|
+
PATH will be prepended to $LOAD_PATH.
|
117
|
+
The \[aq]:\[aq] character may be used to delimit multiple
|
118
|
+
directories.
|
119
|
+
This directive may be used more than once.
|
120
|
+
Modifications to $LOAD_PATH take place immediately and in the order
|
121
|
+
they were specified on the command-line.
|
122
|
+
.RS
|
123
|
+
.RE
|
124
|
+
.TP
|
125
|
+
.B -r, --require LIBRARY
|
126
|
+
require a specified LIBRARY before executing the application.
|
127
|
+
The "require" statement will be executed immediately and in the
|
128
|
+
order they were specified on the command-line.
|
129
|
+
.RS
|
130
|
+
.RE
|
131
|
+
.SH SIGNALS
|
132
|
+
.PP
|
133
|
+
The following UNIX signals may be sent to Zbatery (only supported
|
134
|
+
on UNIX):
|
135
|
+
.IP \[bu] 2
|
136
|
+
HUP - reexecute the binary and exit the current one
|
137
|
+
.IP \[bu] 2
|
138
|
+
INT/TERM - quick shutdown, quit immediately
|
139
|
+
.IP \[bu] 2
|
140
|
+
QUIT - graceful shutdown, waits for current requests before exiting
|
141
|
+
.IP \[bu] 2
|
142
|
+
USR1 - reopen all logs owned by the master and all workers See
|
143
|
+
Unicorn::Util.reopen_logs for what is considered a log.
|
144
|
+
.IP \[bu] 2
|
145
|
+
USR2 - reexecute the running binary.
|
146
|
+
A separate QUIT should be sent to the original process once the
|
147
|
+
child is verified to be up and running.
|
148
|
+
.SH RACK ENVIRONMENT
|
149
|
+
.PP
|
150
|
+
Accepted values of RACK_ENV and the middleware they automatically
|
151
|
+
load (outside of RACKUP_FILE) are exactly as those in rackup(1):
|
152
|
+
.IP \[bu] 2
|
153
|
+
development - loads Rack::CommonLogger, Rack::ShowExceptions, and
|
154
|
+
Rack::Lint middleware
|
155
|
+
.IP \[bu] 2
|
156
|
+
deployment - loads Rack::CommonLogger middleware
|
157
|
+
.IP \[bu] 2
|
158
|
+
none - loads no middleware at all, relying entirely on RACKUP_FILE
|
159
|
+
.PP
|
160
|
+
All unrecognized values for RACK_ENV are assumed to be
|
161
|
+
\[lq]none\[rq].
|
162
|
+
Production deployments are strongly encouraged to use
|
163
|
+
\[lq]deployment\[rq] or \[lq]none\[rq] for maximum performance.
|
164
|
+
.PP
|
165
|
+
Note that the Rack::ContentLength and Rack::Chunked middlewares are
|
166
|
+
never loaded by default.
|
167
|
+
If needed, they should be individually specified in the
|
168
|
+
RACKUP_FILE, some frameworks do not require them.
|
169
|
+
.SH SEE ALSO
|
170
|
+
.IP \[bu] 2
|
171
|
+
unicorn(1)
|
172
|
+
.IP \[bu] 2
|
173
|
+
rainbows(1)
|
174
|
+
.IP \[bu] 2
|
175
|
+
\f[I]Rack::Builder\f[] ri/RDoc
|
176
|
+
.IP \[bu] 2
|
177
|
+
\f[I]Unicorn::Configurator\f[] ri/RDoc
|
178
|
+
.IP \[bu] 2
|
179
|
+
Zbatery RDoc (http://zbatery.bogomip.org/)
|
180
|
+
.IP \[bu] 2
|
181
|
+
Rack RDoc (http://rack.rubyforge.org/doc/)
|
182
|
+
.IP \[bu] 2
|
183
|
+
Rackup HowTo (http://wiki.github.com/rack/rack/tutorial-rackup-howto)
|
184
|
+
.IP \[bu] 2
|
185
|
+
Rainbows! RDoc (http://rainbows.rubyforge.org/)
|
186
|
+
.SH AUTHOR
|
187
|
+
Zbatery hackers <rainbows-talk@rubyforge.org>
|