Created
January 16, 2016 02:06
-
-
Save mvastola/60e490aa83a6b3735b73 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'bundler/inline' | |
gemfile do | |
source 'https://rubygems.org' | |
gem 'passenger', '~> 5.0.x' | |
end | |
require 'timeout' | |
require 'net/http' | |
require 'bundler/cli' | |
require 'bundler/cli/install' | |
# The following module courtesy @tylergannon (license TBD) via https://gist.github.com/tylergannon/7690997 | |
module Net | |
# Overrides the connect method to simply connect to a unix domain socket. | |
class SocketHttp < HTTP | |
attr_reader :socket_path | |
# URI should be a relative URI giving the path on the HTTP server. | |
# socket_path is the filesystem path to the socket the server is listening to. | |
def initialize(uri, socket_path) | |
@socket_path = socket_path | |
super(uri) | |
end | |
# Create the socket object. | |
def connect | |
@socket = Net::BufferedIO.new UNIXSocket.new socket_path | |
on_connect | |
end | |
# Override to prevent errors concatenating relative URI objects. | |
def addr_port | |
File.basename(socket_path) | |
end | |
end | |
end | |
require 'phusion_passenger' | |
PhusionPassenger.locate_directories | |
PhusionPassenger.require_passenger_lib 'standalone/main' | |
class PassengerApp | |
attr_reader :log | |
def initialize(rackup_contents) | |
@tmpdir = Dir.mktmpdir | |
ObjectSpace.define_finalizer(self) do | |
FileUtils.remove_entry @tmpdir if File.exists?(@tmpdir) | |
end | |
@files = Hash.new do |h, k| | |
h[k] = File.join(@tmpdir, k.to_s).freeze | |
end | |
File.write @files['Gemfile'], <<-EOF | |
source 'https://rubygems.org' | |
gem 'rack' | |
gem 'airbrake', :github => 'Partyista/airbrake', :branch => 'master' | |
EOF | |
Dir.chdir @tmpdir | |
File.write(@files['config.ru'], rackup_contents) | |
Bundler::CLI::Install.new({}).run | |
@ran = false | |
@threads = {} | |
end | |
def run! | |
return false if @ran | |
@ran = true | |
args = [ | |
@tmpdir, | |
'--no-install-runtime', | |
'--no-compile-runtime', | |
'--rackup', @files['config.ru'], | |
'--log-file', @files[:log], | |
'--pid-file', @files[:pid], | |
'--socket', @files[:socket], | |
'--min-instances', '0', | |
'--log-level', '1', | |
'--max-pool-size', '1', | |
'--engine', 'builtin' | |
] | |
@threads[:server] = Thread.new do | |
Dir.chdir @tmpdir | |
$stdout = File.open('/dev/null', 'w') | |
PhusionPassenger::Standalone.run!(['start', *args]) | |
end | |
sleep 0.5 until File.exists?(@files[:socket]) | |
@threads[:requester] = Thread.new do | |
begin | |
Timeout::timeout(10) do | |
http = Net::SocketHttp.new('/', @files[:socket]) | |
resp = http.request_get('/') | |
puts "Server replied with status code #{resp.code}." | |
end | |
rescue Timeout::Error | |
puts "Request to server timed out." | |
end | |
end | |
@threads[:requester].join | |
if File.exists?(@files['pid.lock']) | |
PhusionPassenger::Standalone.run!(['stop', '--pid-file', @files[:pid]]) | |
end | |
@threads[:server].join(10) if @threads[:server] && @threads[:server].alive? | |
pid = File.read(@files[:pid]) if File.exists?(@files[:pid]) | |
Process.kill('TERM', pid) if pid && @threads[:server].alive? | |
if pid && Process.kill(0, pid) | |
warn 'Passenger still alive!!!' | |
Process.kill('KILL', pid) | |
end | |
@log = File.read(@files[:log]).freeze | |
FileUtils.remove_entry @tmpdir | |
@tmpdir = nil | |
true | |
end | |
end | |
# Sample Test | |
rackup = <<-EOF | |
require 'rubygems' | |
require 'bundler/setup' | |
Bundler.require(:default) | |
Airbrake.configure do |c| | |
c.project_id = 01234567 | |
c.project_key = 'abcdef0123456789' | |
end | |
raise 'test' | |
EOF | |
test_app = PassengerApp.new rackup | |
test_app.run! | |
puts test_app.log |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment