From 4d77ce83478997d88418ec51d1cce26568d094d2 Mon Sep 17 00:00:00 2001 From: Evan Phoenix Date: Tue, 25 Sep 2012 09:34:10 -0700 Subject: [PATCH] Add options to daemonize puma Previously I was opposed to these options because I felt like puma should always be run under another monitoring process. But after doing some thinking (and some deployment of puma) I realized that the daemon option is simply too useful to not include. I highly suggest it be used with -w, so that if a worker crashes the whole server doesn't mysteriously disappear. --- lib/puma/cli.rb | 33 +++++++++++++++++++++++++++++---- lib/puma/configuration.rb | 22 ++++++++++++++++++++++ lib/puma/daemon_ext.rb | 20 ++++++++++++++++++++ 3 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 lib/puma/daemon_ext.rb diff --git a/lib/puma/cli.rb b/lib/puma/cli.rb index 0448abd4..e668af90 100644 --- a/lib/puma/cli.rb +++ b/lib/puma/cli.rb @@ -6,6 +6,7 @@ require 'puma/const' require 'puma/configuration' require 'puma/binder' require 'puma/detect' +require 'puma/daemon_ext' require 'rack/commonlogger' require 'rack/utils' @@ -159,7 +160,8 @@ module Puma :quiet => false, :debug => false, :binds => [], - :workers => 0 + :workers => 0, + :daemon => false } @parser = OptionParser.new do |o| @@ -171,6 +173,15 @@ module Puma @options[:config_file] = arg end + o.on "-d", "--daemon", "Daemonize the server into the background" do + @options[:daemon] = true + @options[:quiet] = true + end + + o.on "--dir DIR", "Change to DIR before starting" do |d| + @options[:directory] = d.to_s + end + o.on "-I", "--include PATH", "Specify $LOAD_PATH directories" do |arg| $LOAD_PATH.unshift(*arg.split(':')) end @@ -321,6 +332,10 @@ module Puma exit 1 end + if dir = @options[:directory] + Dir.chdir dir + end + clustered = @options[:workers] > 0 if clustered @@ -407,7 +422,11 @@ module Puma log "*** Sorry signal SIGTERM not implemented, gracefully stopping feature disabled!" end - log "Use Ctrl-C to stop" + if @options[:daemon] + Process.daemon(true) + else + log "Use Ctrl-C to stop" + end begin server.run.join @@ -538,9 +557,15 @@ module Puma # @check_pipe, @suicide_pipe = IO.pipe - spawn_workers + if @options[:daemon] + Process.daemon(true) + STDOUT.reopen "/tmp/puma.out", "a" + STDOUT.reopen "/tmp/puma.err", "a" + else + log "Use Ctrl-C to stop" + end - log "* Use Ctrl-C to stop" + spawn_workers begin while !stop diff --git a/lib/puma/configuration.rb b/lib/puma/configuration.rb index 56dba5f4..a8cd897b 100644 --- a/lib/puma/configuration.rb +++ b/lib/puma/configuration.rb @@ -156,6 +156,12 @@ module Puma @options[:binds] << url end + # Daemonize the server into the background. Highly suggest that + # this be combined with +pidfile+ and +stdout_redirect+. + def daemonize(which=true) + @options[:daemon] = which + end + # Set the environment in which the Rack's app will run. def environment(environment) @options[:environment] = environment @@ -187,6 +193,17 @@ module Puma @options[:rackup] = path.to_s end + # Redirect STDOUT and STDERR to files specified. + def stdout_redirect(stdout=nil, stderr=nil, append=false) + if stdout + STDOUT.reopen stdout, (append ? "a" : "w") + end + + if stderr + STDOUT.reopen stderr, (append ? "a" : "w") + end + end + # Configure +min+ to be the minimum number of threads to use to answer # requests and +max+ the maximum. # @@ -220,6 +237,11 @@ module Puma def workers(count) @options[:workers] = count.to_i end + + # The directory to operate out of. + def directory(dir) + @options[:directory] = dir.to_s + end end end end diff --git a/lib/puma/daemon_ext.rb b/lib/puma/daemon_ext.rb new file mode 100644 index 00000000..c63ced4b --- /dev/null +++ b/lib/puma/daemon_ext.rb @@ -0,0 +1,20 @@ +module Process + def self.daemon(nochdir=false, noclose=false) + exit if fork # Parent exits, child continues. + + Process.setsid # Become session leader. + + exit if fork # Zap session leader. See [1]. + + Dir.chdir "/" unless nochdir # Release old working directory. + + if !noclose + null = File.open "/dev/null" + STDIN.reopen null + STDOUT.reopen null + STDERR.reopen null + end + + 0 + end unless respond_to?(:daemon) +end