Heroku+Rails4+Unicorn 反复崩溃,日志中没有有用的输出
Heroku+Rails4+Unicorn Repeated Crashes With No Helpful Output in Log
我在 Heroku 上 运行 数十个 Rails 应用程序,它们的代码非常相似,配置几乎相同。这个特定的应用程序在启动后立即崩溃。好像这还不够糟糕,日志中确实 nothing 表明出了什么问题。这是一个日志示例。
2016-01-14T05:56:13.776324+00:00 heroku[api]: Set LOG_LEVEL, SECRET_TOKEN config vars by karl@kandrsoftware.com
2016-01-14T05:56:13.776324+00:00 heroku[api]: Release v13 created by karl@kandrsoftware.com
2016-01-14T05:56:13.913292+00:00 heroku[web.1]: State changed from crashed to starting
2016-01-14T05:56:16.422157+00:00 heroku[web.1]: Starting process with command `bundle exec unicorn -p 32001 -c ./config/unicorn.rb`
2016-01-14T05:56:20.695481+00:00 heroku[web.1]: State changed from starting to crashed
2016-01-14T05:56:20.692142+00:00 heroku[web.1]: Process exited with status 1
2016-01-14T05:56:37.932488+00:00 heroku[web.1]: State changed from crashed to starting
2016-01-14T05:56:41.228603+00:00 heroku[web.1]: Starting process with command `bundle exec unicorn -p 17696 -c ./config/unicorn.rb`
2016-01-14T05:56:47.053145+00:00 heroku[web.1]: Process exited with status 1
2016-01-14T05:56:47.077114+00:00 heroku[web.1]: State changed from starting to crashed
这是我的 Procfile
:
web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb
worker: bundle exec sidekiq -C config/sidekiq.yml
这是我的 unicorn.rb
:
pid "tmp/pids/unicorn.pid"
stdout_path "log/unicorn.log"
stderr_path "log/unicorn-err.log"
worker_processes Integer(ENV["WEB_CONCURRENCY"] || 3)
timeout 30
preload_app true
require 'fileutils'
FileUtils.mkdir_p 'tmp/pids/' unless File.exist? 'tmp/pids/'
FileUtils.mkdir_p 'log/' unless File.exist? 'log/'
before_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
Process.kill 'QUIT', Process.pid
end
if defined?(ActiveRecord::Base)
ActiveRecord::Base.connection.disconnect!
Rails.logger.info('Disconnected from ActiveRecord')
end
sleep 1
end
after_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
end
if defined?(ActiveRecord::Base)
ActiveRecord::Base.establish_connection
Rails.logger.info('Connected to ActiveRecord')
end
end
我不明白我错过了什么。
我尝试使用 RAILS_ENV=production
对 heroku local
进行故障排除,应用程序启动正常。
使用 heroku run bash
在 Heroku 上登录 bash 允许我从 Heroku 上的 CLI 启动应用程序就好了。
~ $ cat Procfile
web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb
~ $ echo $PORT
9446
~ $ bundle exec unicorn -p $PORT -c ./config/unicorn.rb
~ $
2016-01-14T07:02:30.618120+00:00 heroku[api]: Starting process with command `bash` by karl@kandrsoftware.com
2016-01-14T07:02:33.058993+00:00 heroku[run.2370]: Awaiting client
2016-01-14T07:02:33.085689+00:00 heroku[run.2370]: Starting process with command `bash`
2016-01-14T07:02:33.501795+00:00 heroku[run.2370]: State changed from starting to up
啊!我想通了!
我能够看到 Heroku 上的独角兽日志是这样的:
~ $ less log/unicorn-err.log
所以,原来是一个简单的缺少配置变量。
此外,日志记录和 PID 位置是从 Linode 上的应用程序 运行 中提取的,不应在 Heroku 配置文件中。
应该是这样的:
worker_processes Integer(ENV["WEB_CONCURRENCY"] || 3)
timeout 30
preload_app true
before_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
Process.kill 'QUIT', Process.pid
end
if defined?(ActiveRecord::Base)
ActiveRecord::Base.connection.disconnect!
Rails.logger.info('Disconnected from ActiveRecord')
end
sleep 1
end
after_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
end
if defined?(ActiveRecord::Base)
ActiveRecord::Base.establish_connection
Rails.logger.info('Connected to ActiveRecord')
end
end
(参考:Heroku Dev Center: Deploying Rails Applications with Unicorn)
如果不通过 stdout_path
和 stderr_path
指令重定向输出,则可以从 heroku logs -t
.
中看到错误消息
又一个我妨碍自己的例子。
我在 Heroku 上 运行 数十个 Rails 应用程序,它们的代码非常相似,配置几乎相同。这个特定的应用程序在启动后立即崩溃。好像这还不够糟糕,日志中确实 nothing 表明出了什么问题。这是一个日志示例。
2016-01-14T05:56:13.776324+00:00 heroku[api]: Set LOG_LEVEL, SECRET_TOKEN config vars by karl@kandrsoftware.com 2016-01-14T05:56:13.776324+00:00 heroku[api]: Release v13 created by karl@kandrsoftware.com 2016-01-14T05:56:13.913292+00:00 heroku[web.1]: State changed from crashed to starting 2016-01-14T05:56:16.422157+00:00 heroku[web.1]: Starting process with command `bundle exec unicorn -p 32001 -c ./config/unicorn.rb` 2016-01-14T05:56:20.695481+00:00 heroku[web.1]: State changed from starting to crashed 2016-01-14T05:56:20.692142+00:00 heroku[web.1]: Process exited with status 1 2016-01-14T05:56:37.932488+00:00 heroku[web.1]: State changed from crashed to starting 2016-01-14T05:56:41.228603+00:00 heroku[web.1]: Starting process with command `bundle exec unicorn -p 17696 -c ./config/unicorn.rb` 2016-01-14T05:56:47.053145+00:00 heroku[web.1]: Process exited with status 1 2016-01-14T05:56:47.077114+00:00 heroku[web.1]: State changed from starting to crashed
这是我的 Procfile
:
web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb
worker: bundle exec sidekiq -C config/sidekiq.yml
这是我的 unicorn.rb
:
pid "tmp/pids/unicorn.pid"
stdout_path "log/unicorn.log"
stderr_path "log/unicorn-err.log"
worker_processes Integer(ENV["WEB_CONCURRENCY"] || 3)
timeout 30
preload_app true
require 'fileutils'
FileUtils.mkdir_p 'tmp/pids/' unless File.exist? 'tmp/pids/'
FileUtils.mkdir_p 'log/' unless File.exist? 'log/'
before_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
Process.kill 'QUIT', Process.pid
end
if defined?(ActiveRecord::Base)
ActiveRecord::Base.connection.disconnect!
Rails.logger.info('Disconnected from ActiveRecord')
end
sleep 1
end
after_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
end
if defined?(ActiveRecord::Base)
ActiveRecord::Base.establish_connection
Rails.logger.info('Connected to ActiveRecord')
end
end
我不明白我错过了什么。
我尝试使用 RAILS_ENV=production
对 heroku local
进行故障排除,应用程序启动正常。
使用 heroku run bash
在 Heroku 上登录 bash 允许我从 Heroku 上的 CLI 启动应用程序就好了。
~ $ cat Procfile
web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb
~ $ echo $PORT
9446
~ $ bundle exec unicorn -p $PORT -c ./config/unicorn.rb
~ $
2016-01-14T07:02:30.618120+00:00 heroku[api]: Starting process with command `bash` by karl@kandrsoftware.com 2016-01-14T07:02:33.058993+00:00 heroku[run.2370]: Awaiting client 2016-01-14T07:02:33.085689+00:00 heroku[run.2370]: Starting process with command `bash` 2016-01-14T07:02:33.501795+00:00 heroku[run.2370]: State changed from starting to up
啊!我想通了!
我能够看到 Heroku 上的独角兽日志是这样的:
~ $ less log/unicorn-err.log
所以,原来是一个简单的缺少配置变量。
此外,日志记录和 PID 位置是从 Linode 上的应用程序 运行 中提取的,不应在 Heroku 配置文件中。
应该是这样的:
worker_processes Integer(ENV["WEB_CONCURRENCY"] || 3)
timeout 30
preload_app true
before_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
Process.kill 'QUIT', Process.pid
end
if defined?(ActiveRecord::Base)
ActiveRecord::Base.connection.disconnect!
Rails.logger.info('Disconnected from ActiveRecord')
end
sleep 1
end
after_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
end
if defined?(ActiveRecord::Base)
ActiveRecord::Base.establish_connection
Rails.logger.info('Connected to ActiveRecord')
end
end
(参考:Heroku Dev Center: Deploying Rails Applications with Unicorn)
如果不通过 stdout_path
和 stderr_path
指令重定向输出,则可以从 heroku logs -t
.
又一个我妨碍自己的例子。