本日も実装を進めていきます。
本日はActivehash の導入からしていきます。
Activehash とは、
データベースに保存する必要のない(固定されている)情報を
プルダウンで選択してもらう時などに使用します。
順調に実装は進み、ActiveHash 実装のデプロイをしている最中、
エラーが発生しました。
現状説明
タスク管理機能実装にて、ActiveHashを導入・実装 モデルにてバリデーションを記述、エラーハンドリング実装後、 GitHubにてcommit → push 後、 bundle exec cap production deploy コマンドを実行し、 デプロイの最中にエラー発生
エラー文
undle exit status: 1 (SSHKit::Runner::ExecuteError) bundle stdout: Nothing written bundle stderr: master failed to start, check stderr log for details
①何が問題でどうしたい
エラーを解決し、デプロイを完了する
②現在(位置)
デプロイの途中まで
③問題点
エラーが発生し、デプロイを完了できない
④仮説
エラー文自体は具体的な原因を示していませんが、
「master failed to start, check stderr log for details」という文から、
何らかの問題によりUnicornのマスタープロセスが
起動できなかったことが分かります。
また、具体的なエラーの詳細はstderrのログに書き出されています。
ということ。
探す場所(stderrのログ)が見つかったのでそこを探しに行きます。
⑤試したこと
1️⃣場所(存在するのか) 場所の確認
(そもそも見つからないと言われているものは存在するのか)
エラー文の「master failed to start, check stderr log for details」
stderr log にはエラが発生した時の詳細な情報が記録されています。
stderrのログ はあるのかを探しに行きます。
とは言いつつもどこにあるのか見当もつかないので調べます。
具体的にどこを確認すれば良いのか調べたところ、
config/unicorn.rb もしくは config/unicorn/production.rb
が、あるかを確認せよとのこと
早速、確認へ行くとありました。
config/unicorn.rb
存在していたら、
そのファイルを開いてstderrのパスが設定されている行を探してみてください。
具体的には、stderr_pathという文字が含まれている行を探してみてください。
とのことだったので確認するとありました。
#エラーのログを記録するファイルを指定 stderr_path "#{app_path}/shared/log/unicorn.stderr.log"
このことから分かることは、
Unicornのエラーログはshared/log/unicorn.stderr.log
というファイルパスに
保存されるように設定されているということ。unicorn.stderr.log
の内容を確認するために必要なコマンドは2あります。
cd (プロジェクトディレクトリ)/shared/log cat unicorn.stderr.log
cd (プロジェクトディレクトリ)/shared/log とは、
現在作成しているアプリケーションのディレクトリまで移動し、
sharedディレクトリ傘下の logディレクトリまで辿り着くコマンド
cat unicorn.stderr.log とは、
cat unicorn.stderr.log の内容(エラーが発生した時の詳細な情報)を見るコマンド
上記2つのコマンドを本番環境で実行する。
※本番環境とは、EC2インスタンスへログイン すること。
しかし、
cd (プロジェクトディレクトリ)/shared/log を実行するも
プロジェクトディレクトリが見つからない。
lsコマンドでも、内容は空でした。
shared/logディレクトリに移動するために、
まずは プロジェクトディレクトリを探します。
cd / で一度ホームディレクトリに戻り、ls でリストを出します。
homeディレクトリを調べるも、不発に終わり、opt でも見当たらず。
var/www/ の中でやっと プロジェクトディレクトリを見つけることができました。
これで、1つ目のコマンドが実行できます。
cd (プロジェクトディレクトリ)/shared/log
コマンド実行
logディレクトリに移動し、ls でリストを確認
2行目マーカー部にて、
今回のエラー解決の鍵を握る unicorn.stderr.log を見つけることができました。
そして、3行目で、2つ目のコマンドを実行しました。
cat unicorn.stderr.log
ログを確認すると、今回のエラーの根幹を見つけました。
NoMethodError
メソッドが見つからないという意味です。
validetes と なっているが本当は、validates ではないのか? と忠告されていました。
指摘されている場所は Task:Class なので、
app/models/task.rb を確認しに行きます。
app/models/task.rb 場所は ありました。
2️⃣前提&置換((構文的に)正しく設定されているか)
前提の確認(記述の仕方は(構文的に)正しいか))
正しい構文で、値は正しく置き換わっているか
記述の仕方は構文的に正しいか
app/models/task.rb
class Task < ApplicationRecord extend ActiveHash::Associations::ActiveRecordExtensions belongs_to :category belongs_to :user #空の投稿を保存できないようにする validates :task_name, presence: true validates :description, presence: true validates :deadline, presence: true #ジャンルの選択が「---」の時は保存できないようにする validetes :category_id, numericality: { other_than: 1 ,message: "can't be blank"} end
正しくありませんでした
validetes :category_id, numericality: { other_than: 1 ,message: "can't be blank"}
validetes となっていました。
validetes を validates と正しく修正。
再度、commit → push し ローカル環境にて、デプロイを実行。
今度は、ArgumentError が発生しました。
エラーメッセージによれば、
「stderr_path
」というメソッドが引数を1つ期待していますが、
何も渡されていないため、ArgumentErrorが発生しているようです。
したがって、/var/www/hibitumo/current/config/unicorn.rb
内のstderr_path
の設定が間違っている可能性が高いです。
こちらの設定を確認し、適切なパスを引数として渡してみてください。
とのこと。
今から調べに行く場所は、unicorn.rb
です。
1️⃣場所(存在するのか) 場所の確認
(そもそも見つからないと言われているものは存在するのか)
/var/www/(プロジェクトディレクトリ)/current/config/unicorn.rb は先程と同じ、
config/unicorn.rb 内にある
2️⃣前提&置換((構文的に)正しく設定されているか)
前提の確認(記述の仕方は(構文的に)正しいか))
正しい構文で、値は正しく置き換わっているか
記述の仕方は構文的に正しいのか
#エラーのログを記録するファイルを指定 stderr_path "#{app_path}/shared/log/unicorn.stderr.log"
以下の2つを調べる
app_path変数は適切に設定されているか ログファイルの出力先として設定されているディレクトリ(#{app_path}/shared/log/)は存在しているか
app_path変数は適切に設定されているか
app_path
変数の設定は、
同じunicorn.rb
ファイル内で定義または設定されているはずです。
そのため、その設定を探すためには、再度unicorn.rb
ファイルを開き、
がどのように設定されているか確認してみてください。
app_path
とのこと。
#サーバ上でのアプリケーションコードが設置されているディレクトリを変数に入れておく app_path = File.expand_path('../../../', __FILE__)
ターミナル(ローカル)
コマンドを実行して File.expand_path("../../../", FILE) の値を確認する
# ruby -r fileutils -e 'puts File.expand_path("../../../", __FILE__)' # 出力結果 => /User/***
ターミナル(ローカル)
ls コマンドを使ってshared/log があるかを確認する
# ls /User/***/shared/log/ # 出力結果 => No such
この結果から、
stderr_path "#{app_path}/shared/log/unicorn.stderr.log" shared/log がない
ということは、/unicorn.stderr.log がないということになる。
しかし、ついさっきまであった、
/unicorn.stderr.log がなくなるとはどういうことなのだろうか?
再度、本番環境で unicorn.stderr.log を探してみることにした。
EC2(本番環境)
# プロジェクトリポジトリへ移動 # cd /var/www/プロジェクトリポジトリ # ls でディレクトリを確認 # 出力結果 => shared の存在を確認 # shared/logへ移動 # cd shared/log # ls でディレクトリを確認 # 出力結果 => unicorn.stderr.log の存在を確認 # unicorn.stderr.log の中身を確認する # cat unicorn.stderr.log # 出力結果 => 中身を確認することができた デプロイが成功していないため、 NoMethodError で 修正した箇所はまだ反映されていなかった
結果、確かにデプロイ前には存在していた unicorn.stderr.log が
NoMethodError のスペルを1つ修正しただけでなくなったということ。
そのようなことがあるのだろうか。
考えを整理してみると、
stderr_path "#{app_path}/shared/log/unicorn.stderr.log" に対して、
ローカル環境では、
stderr_path で 期待する変数 を受け取れない(/shared/log がない)
本番環境では、
エラーが発生した瞬間までは stderr_path で期待する変数を受け取れていた
ここで新たな仮説が出てきた
「もう1つ stderr_pathメソッド が存在するのではないか」
念の為、もう一度、config/unicorn.rb を見てみると、
末尾にエラーの根幹を見つけることができました。
stderr_path の 空メソッドです。
すなわち、正しく設定されていませんでした。
3️⃣内容((構文的に)正しく情報を受け取っているか)
内容の確認(構文的に)そこに記述されている内容は正しいか)
(構文的に)正しい設定・値に置き換えられているなら、
正しい情報を受け取っているのか
stderr_pathメソッドは正しい情報を受け取っていなかった。
⑥結果
空の stderr_pathメソッドを削除し、再度、デプロイを実行
無事にデプロイを完了することができました。
原因:
NoMethodError: スペルミス。
ArgumentError : stderr_path の空メソッドが期待する変数を受け取れなかったため。 stderr_path が末尾にあった理由は、NoMethodError を解決する際、
stderr_path を検索するために記述し、その後 削除し忘れたためである。
解決方法:
NoMethodError: スペルミス
スペル修正。
ArgumentError : stderr_path の空メソッドが期待する変数を受け取れなかったため
空メソッドを削除。
気付き:
スペルミスが多いが、エラーを見つける速度は早くなってきているように思います。
ArgumentEroor に関しては、
期待1の場合
given 0 , expected 1
予期せぬメソッドの存在がある可能性を示唆しているということを学ぶことができました。
また、実装と関係ない記述をした場合は削除を忘れないようにする。