RailsアプリケーションのAWSへのデプロイ時に起こるエラーの解決方法まとめ

#1.例として取り扱うエラーの様子

わかりやすくするために筆者の出会ったエラーを見ながら解説します。

＜例として取り扱うエラー文の該当部分のみ抜粋＞

```
Errno::ENOENT: No such file or directory @ dir_s_chdir
SSHKit::Runner::ExecuteError: Exception while executing as ec2-user@3.115.38.38: bundle exit status: 1
```

＜エラー文の周辺ありの様子＞

```
Traceback (most recent call last):
        1: from /Users/kontatomoya/.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/kontatomoya/.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 ec2-user@3.115.38.38: bundle exit status: 1 (SSHKit::Runner::ExecuteError)
bundle stdout: Nothing written
bundle stderr: bundler: failed to load command: unicorn (/var/www/freemarket_sample_62d/shared/bundle/ruby/2.5.0/bin/unicorn)
Errno::ENOENT: No such file or directory @ dir_s_chdir - /var/www/freemarket_sample_62d/current/current
〜中略〜
master failed to start, check stderr log for details
(Backtrace restricted to imported tasks)
cap aborted!
SSHKit::Runner::ExecuteError: Exception while executing as ec2-user@3.115.38.38: bundle exit status: 1
bundle stdout: Nothing written
bundle stderr: bundler: failed to load command: unicorn (/var/www/freemarket_sample_62d/shared/bundle/ruby/2.5.0/bin/unicorn)
Errno::ENOENT: No such file or directory @ dir_s_chdir - /var/www/freemarket_sample_62d/current/current

```

#2.エラー例の原因

エラー文を読めば、"テスト環境のテーブルフォルダがない"、"ssh通信が実行できていないのでエラーである"という記述となっており、ローカルでは見たことのないエラーが起きますが、エラーになる理由に目星をつけられていれば下記のように原因と解決方法をすぐ理解することができます。

#####①"Errno::ENOENT: No such file or directory @ dir_s_chdir"
　→フォルダの読み取りに失敗しているから、unicorn.rbのpathの指定のための変数のディレクトリ指定がずれているのだろう。いざ確認すると下記の通り。

```ruby:config/unicorn.rb
app_path = File.expand_path('../../../', __FILE__)
#この行の../が一多い。そのため、ワーキングディレクトリにズレが生じ、dir_s_chdirがあるべきところに存在しないという現象となっていた
```

#####②"SSHKit::Runner::ExecuteError: Exception while executing as ec2-user@3.115.38.38: bundle exit status: 1"
　→セキュリティの設定（ssh）ではなく、通信（Runner）エラーという形でエラーだろう。ではunicornの再起動で治る


#3.エラー例の解決方法

このエラー文が出た時は①を`../`の削除により直したのち、おかしいディレクトリ状態で起動しているnginx,unicornを一度再起動すれば②が治ります。

※もし正しく直ってない場合本番環境で`RAILS_SERVE_STATIC_FILES=1 bundle exec unicorn_rails -c config/unicorn.rb -E production -D`すると実行できず、エラー文が出るのでそれで判断することができます。

ちなみにcapistranoで自動デプロイのコマンドを打つと、正しく起動できるバージョンを選択して起動してくれてしまうため、裏に潜んでいるエラーに気づくことはできません。

なので、本番環境のコマンドラインからunicornを起動して、問題なければ`bundle exec cap deploy exec`する癖をつけると最新バージョンのデプロイのエラーの有無に気づけるため、そのようにすることをお勧めします。

また余談ですが、ディレクトリの間違いでデプロイ時に顕著になりやすいのがscssが当たらない現象ですので覚えておくとエラー解決が捗るかと思います。（コンパイルファイルまでのpathがおかしくなるため検証のconsoleを見ると erro 500 no applicationxxxx.css file になっています）


#4.デプロイのエラー全般に関する解決方法まとめ
このようにエラーが起きた時に、大抵下記の3つに収束すると理解できているとデプロイでのエラー対応が素早く行うことができるようになります。

#####①mysql,unicornが最新バージョンではないところで起動してしまっている
（unicornの起動のタイミングでアプリケーションが`/var/www/アプリ名/release/起動日時フォルダ`にコピーとして残るためその読み取りでエラーがよく起きます。ちなみに動作中のアプリは`/var/www/アプリ名/currentフォルダ`に格納され起動されています）

 →・mysqlが疑わしければ
（初期開発なら）`RAILS_ENV=production DISABLE_DATABASE_ENVIRONMENT_CHECK=1 bundle exec rake db:drop`ののち`RAILS_ENV=production bundle exec rake db:create`と`RAILS_ENV=production bundle exec rake db:migrate`でテーブルを作り直してしまいましょう。
（サービス開始中なら）ローカルで動作確認が終わったものを`git pull origin master`し、`RAILS_ENV=production bundle exec rake db:create`と`RAILS_ENV=production bundle exec rake db:migrate`しましょう

・unicornが疑わしければ`ps aux|grep unicorn`で起動中のunicornのプロセス番号を調べて`kill`コマンドをうち、`bundle exec unicorn_rails -c config/unicorn.rb -E production -D`コマンドでunicornを再起動しましょう


#####②gemがコンフリクトしている

→・gemのバージョンでコンフリクトし、`bundle install`できない場合
`rm Gemfile.lock`でGemfile.lockを削除し該当するgemのバージョンをダウングレードしましょう。ダウングレードの方法は下記の記事に記載しました。（下記のものはbundlerだけについて書いてありますが、基本的にどのgemでも同じ方法でダウングレードを行います）
https://qiita.com/KONTA2019/items/068d813330e1a0f2de5c

・イメージアップローダを複数使用してしまっている場合（特にcarrierwaveとactive_storageを両方入れてしまっている場合）
イメージとして保存されるかハッシュとして保存されるかで違いが出るためS3が読み取ることができなくなります。片方に関する記述をローカルで消したのちに`git pull origin master`してunicornを再起動しましょう（①のunicornのコマンドと同じ作業をしましょう）


#####③gemなどのpathに関する記載を間違っている。
pathが書いてあるのは主に下記のところとなります。
・config/unicorn.rbやconfig/deploy.rbなどのconfig直下のファイル全般
・/etc/nginx/config.d/rails.conf

→まずローカルのエディターでconfig/unicorn.rbやconfig/deploy.rbなどのconfig直下のファイル全般に誤りがないか調べましょう。
その後EC2にログイン後`cd /etc/nginx/conf.d`でディレクトリを変えたのち`sudo vim rails.conf`で権限ありでvimを使用してnginxの設定に誤りがないか確認・修正しましょう。/etc/nginx/config.d/rails.confを修正した時は`sudo service nginx restart`コマンドでnginxを再起動しましょう。


※sshの通信やmysqlの設定（ソケットエラーなど）に関しては、初期の環境構築の時以外はほとんど原因ではなく、railsのバージョンを上げない限りエラーにはならないため、たとえエラー文で出てきても最後の最後まで触らない方が良いと思います。（大抵の原因が古いデプロイデータを読んでいるために起こるエラーなので、だいたいは起動中のunicorn,nginx,mysqlの再起動で治るか、別のエラー文が出現します。）
ただし例外的に、中途半端なログアウト（テーブルの作り直しのあとにunicornの再起動を忘れたりなど）をすると、mysqlのpidファイルでエラーが起きることはあるのでその時は`kill -3`コマンド（下記の記事を参照）でエラーを解消しましょう。（この作業をしないとunicornの再起動ができなくなっています。また、`kill -3`を終えたら忘れずにunicornを再起動しましょう）
https://qiita.com/President_Taka/items/e7d3c79154a817625b95

#5.どうしてもエラーが見つけられない人へ
<忙しい方へ>
エラー文に記載されているファイルを見てみましょう。きっと何か掴めると思います

<詳しい説明>
筆者もデプロイを設定し始めの頃はデプロイというもののイメージがわかないため、見つけることはおろかエラー内容の想定もできませんでした。
あるときエラー文にディレクトリの指定があることに気づき、`cd(チェンジディレクトリ)`コマンドでその中に入り、`ls(中にあるファイルやフォルダの一覧を表示する)`や`sudo vim ファイル名（vimというエディターでファイルを開く)`コマンドを打って、エラーが起きている場所は実際どのような記述（または配置）となっているのかをエラー文からではなく自分の目で直接ファイルを見ていきました。するとエラーの原因がローカルのエラーに近しい（ターミナルに打つコマンドが違ったり、エラーを見るためのコマンドが必要だったりするだけ）ということに気がつき、そこからエラー発見が容易になっていきました。

このように行き詰まってしまった方は、一度初心に戻り、エラーの原因のファイルのあるところまでコマンドラインを使って潜り込んで見ると分かることがあるかもしれないため、この作業をお勧めします。