【unicorn】master failed to start, check stderr log for detailsの解決法

# なにこれ
筆者がcapistranoでデプロイをするときに、
「master failed to start, check stderr log for details」
のエラーに7時間悩まされた話
#
```
01:57 unicorn:start
      01 $HOME/.rbenv/bin/rbenv exec bundle exec unicorn -c /var/www/MyNo…
      01 master failed to start, check stderr log for details
```

# 結論
自分の場合はかなり特例だと思います。
credentials.yml.encに以下の内容を追加したら解決しました。
#
```ターミナル.
EDITOR='vim --wait' rails credentials:edit
```
#
```credentials.yml
aws:
  AWS_ACCESS_KEY_ID: <YOUR_AWS_ACCESS_KEY_ID>
  AWS_SECRET_ACCESS_KEY: <YOUR_AWS_SECRET_ACCESS_KEY>
```
「master failed to start, check stderr log for details」で検索すると、
unicornのバージョン変更や編集権限の記事がヒットするのですが、
自分の場合は全く違いました。

# 経緯
VPCの関係でEC2インスタンスを作り直したのが発端です。
既存のアプリを新しいEC2に引っ越ししました。
ほとんど完成した状態でAWSのアクセスキーなどの記述がありました。

手順は後述。
ローカルで【bundle exec cap production deploy】
タイトルのエラーでコケる←ここで7時間ハマる

# エラーログをよく見て原因を考える
#
```ターミナル.
01:57 unicorn:stop
      unicorn is not running...
01:57 unicorn:start
      01 $HOME/.rbenv/bin/rbenv exec bundle exec unicorn -c /var/www/MyNo…
      01 master failed to start, check stderr log for details

#<Thread:0x00007fbc0da2b5e0@/Users/ohishikaido/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/sshkit-1.21.0/lib/sshkit/runners/parallel.rb:10 run> terminated with exception (report_on_exception is true):
Traceback (most recent call last):
        1: from /Users/ohishikaido/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/sshkit-1.21.0/lib/sshkit/runners/parallel.rb:11:in `block (2 levels) in execute'
/Users/ohishikaido/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/sshkit-1.21.0/lib/sshkit/runners/parallel.rb:15:in `rescue in block (2 levels) in execute'

Exception while executing as kaito@3.113.216.56: bundle exit status: 1 (SSHKit::Runner::ExecuteError)
bundle stdout: Nothing written
bundle stderr: master failed to start, check stderr log for details
(Backtrace restricted to imported tasks)

cap aborted!
SSHKit::Runner::ExecuteError: Exception while executing as kaito@3.113.216.56: bundle exit status: 1
bundle stdout: Nothing written
bundle stderr: master failed to start, check stderr log for details

Caused by:
SSHKit::Command::Failed: bundle exit status: 1
bundle stdout: Nothing written
bundle stderr: master failed to start, check stderr log for details
Tasks: TOP => unicorn:start
(See full trace by running task with --trace)

The deploy has failed with an error: Exception while executing as kaito@3.113.216.56: bundle exit status: 1
bundle stdout: Nothing written
bundle stderr: master failed to start, check stderr log for details
```

「01:57 unicorn:start」で失敗してる。
EC2でエラーログを確認してみる。
#
```EC2.
cd /var/www/アプリ名/current/log/
cat unicorn.stderr.log
```
（ここだけ画像です！）
<img width="1055" alt="エラー文.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629015/dfa1141d-18e3-8371-0e3f-27b3636d94cc.png">
aws_accses_key_id と aws_secret_accses_key がArgumentError？？
どういうこと？
そういえば、carrierwaveでAWSのキーを使ってた。
#
```carrierwave.rb
    config.fog_credentials = {
      provider: 'AWS',
      aws_access_key_id: ENV['AWS_ACCESS_KEY_ID'],
      aws_secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
      region: 'ap-northeast-1'
    }
```
上記を以下に変更
#
```carrierwave.rb
    config.fog_credentials = {
      provider: 'AWS',
      aws_access_key_id: Rails.application.credentials.aws[:AWS_ACCESS_KEY_ID],
      aws_secret_access_key: Rails.application.credentials.aws[:AWS_SECRET_ACCESS_KEY],
      region: 'ap-northeast-1'
    }
```
そして、冒頭の結論に書いてあるcredentials.ymlに記述を行う。
commit&pushしてデプロイすると解決しました。

# 感想
一度carrierwave.rbの`ENV['AWS_ACCESS_KEY_ID']`の記述をコメントアウトして
デプロイしてみたんですけど、同じエラーでコケました。
アクセスキーに関する記述があると、どこかでアクセスキーを書いてないとエラーが出るっていう感じなんですね。
勉強になりました！

# 余談
EC2で【sudo vim /etc/environment】を叩いて、
そちらにAWS_ACCESS_KEY_IDとAWS_SECRET_ACCESS_KEYを書いても成功しました。
管理しやすいと思って、credentials.ymlに書くことにしました。

## EC2からユニコーンが再起動できない！問題を解決

### 結論
unicorn.rbのapp_pathの指定を変えるだけ。
#
```config/unicorn.rb
app_path = File.expand_path('/var/www/アプリ名')
```

### 経緯
起動中のユニコーンのプロセスを確認します。
#
```EC2.
ps aux | grep unicorn
```
以下のやつしかいない。ok
#
```EC2.
ec2-user 32720  0.0  0.2 110536  2180 pts/1    S+   22:49   0:00 grep --color=auto unicorn
```
【bundle exec unicorn_rails -c config/unicorn.rb -E production -D】
を叩いても、タイトルのエラーでコケます！
【bundle exec cap production deploy】が通るのに、
EC2のcurrentで通らない。。。謎みが深い。

コマンドを`RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D`に変えてもダメでした。。
`sudo service mysqld restart`もやりました。
#
```エラー文.
bundler: failed to load command: unicorn_rails (/var/www/MyNote/shared/bundle/ruby/2.5.0/bin/unicorn_rails)
ArgumentError: config_file=config/unicorn.rb would not be accessible in working_directory=/var/www/MyNote/releases/current
(中略)
master failed to start, check stderr log for details
```
うーん、原因がよく分からない。
`/var/www/MyNote/releases/current`っていうパスだから、
/MyNote/releases/current/が悪いのは分かる。
そんなパスは存在しないので。
でも、unicorn.rbでパス指定を別にしたら、他エラーが出てきてユニコーンが起動できない。笑
#
```config/unicorn.rb
app_path = File.expand_path('../../', __FILE__)
working_directory "#{app_path}/current"
```
#
```EC2.
bundler: failed to load command: unicorn_rails (/var/www/MyNote/shared/bundle/ruby/2.5.0/bin/unicorn_rails)

ArgumentError: config_file=config/unicorn.rb would not be accessible in working_directory=/var/www/MyNote/releases/20200628222655/current
```
bundle exec unicorn_rails -c config/unicorn.rb -E production -Dを叩いてコケる
`~/MyNote/releases/20200628222655/current`ってどこだよ（哲学）

しょうがないので絶対パスにしてみる。

#
```config/unicorn.rb
app_path = File.expand_path('/var/www/アプリ名')
```
`bundle exec unicorn_rails -c config/unicorn.rb -E production -D`を叩いてコケる
エラーログを`cat log/unicorn.stderr.log`で確認します！
#
```log/unicorn.stderr.log
bundler: failed to load command: unicorn_rails (/var/www/MyNote/shared/bundle/ruby/2.5.0/bin/unicorn_rails)
ArgumentError: Already running on PID:31334 (or pid=/var/www/MyNote/shared/tmp/pids/unicorn.pid is stale)
```
PIDが生きてるのでkillします。
#
```
ps aux | grep unicorn
kill -9 プロセス番号
```
ユニコーン起動できた〜
#
```EC2
ec2-user   612 38.0 11.3 509012 114744 ?       Sl   23:43   0:01 unicorn_rails master -c config/unicorn.rb -E production -D                                                                                            
ec2-user   617  0.0 10.6 510088 107676 ?       Sl   23:43   0:00 unicorn_rails worker[0] -c config/unicorn.rb -E production -D                                                                                         
ec2-user   622  0.0  0.2 110536  2144 pts/1    S+   23:43   0:00 grep --color=auto unicorn
```
今までの手順はEC2からvimでいじっただけなので、`bundle exec cap production deploy`
を叩いてみる。
#
```
00:48 deploy:log_revision
      01 echo "Branch master (at f7a05267807ec5da99859b9a14bf49c494547dac) deployed as release 202…
    ✔ 01 ec2-user@13.114.24.148 0.469s
ohishikaido@ohishi-MacBook-Air my_app % 
```
通りました笑


# 経緯の手順
#
```Gemfile.
# 既にあるグループ内に追記
group :development, :test do
  gem 'pry-rails'
  gem 'capistrano'
  gem 'capistrano-rbenv'
  gem 'capistrano-bundler'
  gem 'capistrano-rails'
  gem 'capistrano3-unicorn'
  gem 'capistrano-rails-console'
end

# 以下全てをGemfile下部にコピー
group :production do
  gem 'unicorn', '5.4.1'
end
```

#
```config/deploy/production.rb
server '自身のElasticIP', user: 'ec2-user', roles: %w{app db web}
```
#
```config/unicorn.rb(新規作成)
# ファイルが無いのでconfigフォルダにunicorn.rbを新規作成します

app_path = File.expand_path('../../../', __FILE__)

worker_processes 1

working_directory "#{app_path}/current"
pid "#{app_path}/shared/tmp/pids/unicorn.pid"
listen "#{app_path}/shared/tmp/sockets/unicorn.sock"
stderr_path "#{app_path}/shared/log/unicorn.stderr.log"
stdout_path "#{app_path}/shared/log/unicorn.stdout.log"

timeout 60

preload_app true
GC.respond_to?(:copy_on_write_friendly=) && GC.copy_on_write_friendly = true

check_client_connection false

run_once = true

before_fork do |server, worker|
  defined?(ActiveRecord::Base) &&
    ActiveRecord::Base.connection.disconnect!

  if run_once
    run_once = false # prevent from firing again
  end

  old_pid = "#{server.config[:pid]}.oldbin"
  if File.exist?(old_pid) && server.pid != old_pid
    begin
      sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
      Process.kill(sig, File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH => e
      logger.error e
    end
  end
end

after_fork do |_server, _worker|
  defined?(ActiveRecord::Base) && ActiveRecord::Base.establish_connection
end
```

#
```config/deploy.rb
# Gemfile.lockを見てcapistranoのバージョンを入れる
lock 'xx.xx.x'

# 自身のアプリ名、リポジトリ名を記述
set :application, 'アプリ名'
set :repo_url,  'git@github.com:githubのユーザー名/リポジトリ名.git'

set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system', 'public/uploads')

set :rbenv_type, :user
set :rbenv_ruby, '2.5.1'

# chat-spaceで使ったpemを指定
set :ssh_options, auth_methods: ['publickey'],
                  keys: ['~/.ssh/xxx.pem']

set :unicorn_pid, -> { "#{shared_path}/tmp/pids/unicorn.pid" }
set :unicorn_config_path, -> { "#{current_path}/config/unicorn.rb" }
set :keep_releases, 5

set :linked_files, %w{ config/master.key }

after 'deploy:publishing', 'deploy:restart'
namespace :deploy do
  task :restart do
    invoke 'unicorn:stop'
    invoke 'unicorn:start'
  end

  desc 'upload master.key'
  task :upload do
    on roles(:app) do |host|
      if test "[ ! -d #{shared_path}/config ]"
        execute "mkdir -p #{shared_path}/config"
      end
      upload!('config/master.key', "#{shared_path}/config/master.key")
    end
  end
  before :starting, 'deploy:upload'
  after :finishing, 'deploy:cleanup'
end
```

#
```config/database.yml
production:
  <<: *default
  database: 本番環境のDB名
  username: root
  password: password
  socket: /var/lib/mysql/mysql.sock
  encoding: utf8
```

EC2で【sudo service mysqld start】を打つ
ローカルで【bundle exec cap production deploy】を打つ

unknown databaseが出るので、EC2の適当な場所で、
　【rails db:create RAILS_ENV=production】を打つ
#
```EC2.
cd /var/www/アプリ名/releases
ll            #=> 日付を表す数字の名前のフォルダが表示される 例：20200218063515
cd 一番下の数字 #=> 例 cd 20200218063515
rails db:create RAILS_ENV=production
```

EC2で【sudo vim /etc/nginx/conf.d/rails.conf】を叩いて編集
#
```rails.conf
upstream app_server {
  server unix:/var/www/アプリ名/shared/tmp/sockets/unicorn.sock;
}

server {
  listen 80;
  server_name ご自身のElastic IP;

  root /var/www/アプリ名/current/public;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
    root   /var/www/アプリ名/current/public;
  }

  try_files $uri/index.html $uri @unicorn;

  location @unicorn {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://app_server;
  }

  error_page 500 502 503 504 /500.html;
}
```

EC2で【sudo service nginx start】を打つ
ローカルで【bundle exec cap production deploy】を叩いてコケる。