When running Puma as a daemon (i.e. using the -d
flag), Puma does not seem to log to the location specified by stdout_redirect
.
Has anyone seen this behavior before and if so, found a workaround to generate the proper log files for Puma (specifically with the stdout_redirect
in place, and specifically for a Ruby on Rails application)?
The reason stdout_redirect
is not working is because config/puma.rb
is never run when you run rails server -d
. You can demonstrate this for yourself by changing the port number or even introducing a syntax error in the file.
Puma runs as a Rack server and is thus launched by the Rack middleware. The Rack code just uses the core Ruby Process
class to detach the process:
def daemonize_app
Process.daemon
end
Unfortunately, Process.daemon
does two things by default:
/dev/null
.So, when the Puma server initializes, all process output is binned and since /config/puma.rb
doesn't exist, puma falls back to its hardcoded default settings.
You can actually demonstrate the behavior you want if you temporarily hack the rack
code to override the chdir behaviour:
def daemonize_app
Process.daemon(true)
end
If the first parameter to .daemon
is true
it does not change the current working directory, and thus the config/puma.rb
gets run.
Short of some kind of ugly monkey-patch to Rack, a (possibly also ugly) workaround would be to skip the -d
option and roll your own in config/puma.rb
. For example:
# ... rest of the puma config
return unless ENV['DAEMONIZE_PUMA'].present?
puts 'Running puma as a daemon...'
Process.daemon(true)
Then:
% export DAEMONIZE_PUMA=true
% rails server
=> Booting Puma
=> Rails 6.1.4 application starting in development
=> Run `bin/rails server --help` for more startup options
Running puma as a daemon...
% tail log/puma.out
=== puma startup: 2021-07-17 10:03:37 +1200 ===