Heroku + Rails4 + Unicorn重复崩溃,日志中没有有用的输出

时间:2016-01-14 06:17:04

标签: ruby-on-rails-4 heroku unicorn

我在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

1 个答案:

答案 0 :(得分:1)

AH!我想通了!

我能够看到Heroku上的独角兽登录:

~ $ less log/unicorn-err.log 

所以,结果是一个简单的缺失配置var。

此外,日志和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_pathstderr_path指令重定向输出,则会从heroku logs -t显示错误消息。

另一个我以自己的方式走的例子。