Skip to content

Instantly share code, notes, and snippets.

@matsadler
Last active October 3, 2018 08:33
Show Gist options
  • Save matsadler/8b4cc374276143593e80 to your computer and use it in GitHub Desktop.
Save matsadler/8b4cc374276143593e80 to your computer and use it in GitHub Desktop.
Simple Ruby app preloader.
#!/usr/bin/env ruby
require "socket"
# This is a simple preloader for Ruby apps.
# Usage:
# Put this file somewhere in your PATH, named 'ruby_preloader' and make sure
# it's executable.
# Add whatever you need to load your app environment to a .preload.rb in the
# base directory of your project.
# Add #!/usr/bin/env ruby_preload as the first line of any script you want to
# run with a preloaded environment.
# Run, and keep running, 'ruby_preload' from the base directory of your project.
# Run your script, it should now load quickly.
script = ARGV.last
exec("ruby", "--version") if script == "--version"
script, reload = nil, true if script == "--reload"
Dir.mkdir("/tmp/ruby_preload") unless File.exist?("/tmp/ruby_preload")
sock_path = "/tmp/ruby_preload/#{Dir.pwd.tr("^a-zA-Z0-9", "_")}_sock"
std_io = [STDIN, STDOUT, STDERR]
if script
abort("ruby_preload server not running") unless File.exist?(sock_path)
sock = UNIXSocket.new(sock_path)
sock.puts(script)
pid = sock.gets.to_i
(Signal.list.keys - %W{ILL FPE BUS SEGV VTALRM KILL STOP}).each do |name|
Signal.trap(name) {Process.kill(name, pid)}
end
std_io.each {|io| sock.send_io(io)}
exit(sock.gets.to_i)
else
server = UNIXServer.new(sock_path)
begin
require "#{Dir.pwd}/.preload" if File.exist?(".preload.rb")
rescue Exception => e
File.unlink(sock_path)
raise
end
is_parent = true
while is_parent
begin
sock = server.accept
script = sock.gets.chomp
is_parent = fork
File.unlink(sock_path) && exec($0, "--reload") if is_parent && reload
rescue Exception => e
File.unlink(sock_path)
Interrupt === e ? exit : raise
end
end
server.close
sock.puts(Process.pid)
std_io.each {|io| io.reopen(sock.recv_io)}
begin
load script
ensure
sock.puts($! ? $!.respond_to?(:status) ? $!.status : 1 : 0)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment