【rails】”No such file or directory @ rb_sysopen – log/production.log”が発生してログのローテションができなかった

目次

この記事で扱うrailsのバージョン

rails 7.0.4.2

ログのローテーションがうまくいかない

rubyのLoggerクラスでログのローテーションを設定したところ、
なぜかログがローテーション後のログファイルに吐き出されていた
15:04 production.log
17:42 production.log.20241111 <- こちらのファイルにログが吐き出されていた

ログの設定はこんな感じ
Rails.application.configure do
  ~~~
  # 日数でローテート
  config.logger = Logger.new("log/production.log", "daily")
  ~~~
end

No such file or directory @ rb_sysopen - log/production.log
がエラーとして出力されていたため出力先の設定を絶対パスにしたところ解決

修正後の設定ファイル
Rails.application.configure do
~~~
# 日数でローテート
config.logger = Logger.new(Rails.root.join("log/production.log"), "daily")
~~~
end

めでたしめでたし

ところで

絶対パスとするべきところを相対パスにするという初歩的なミスが原因でローテションがうまくいっていなかったわけですが、ログ自体は吐き出されているのに、なぜローテーションの時だけ No such file or ~ になってしまうのかがよくわからなかったので少し調査してみました

犯人は Process.daemon

アプリをバックグラウンドで起動するために -d オプションをrailsコマンドにつけてデーモン化していたのですが、これが原因でした

raisコマンドに-dをオプションで渡すと、daemonize_appが呼び出されるのですが、Prodess.daemonを引数なしで呼び出しています
def daemonize_app
  # Cannot be covered as it forks
  # :nocov:
  Process.daemon
  # :nocov:
end

daemon(nochdir = nil, noclose = nil) -> 0

プロセスから制御端末を切り離し、バックグラウンドにまわってデーモンとして動作させます。

カレントディレクトリを / に移動します。ただし nochdir に真を指定したときにはこの動作は抑制され、カレントディレクトリは移動しません。

https://docs.ruby-lang.org/ja/latest/method/Process/m/daemon.html

rubyのProcess.daemonは引数なしで呼び出すと、プロセスのカレントディレクトリを / に移動するようです

ログの初期化時は実行ディレクトリがカレントディレクトリなので相対パスでも問題ないが、デーモン化したタイミングで / に切り替わっていたため、ローテーションの時には相対パスだとログファイルが見つからないと怒られていたわけでした(ちなみに7.1以降のrailsではカレントディレクトリは移動しないようになっています)
def daemonize_app
# Cannot be covered as it forks
# :nocov:
Process.daemon(true, options[:daemonize] == :noclose)
# :nocov:
end

役に立ったらシェアしていただけると嬉しいです
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次