私はルビー標準ロガーを使用しています。毎日ローテーションしたいので、私のコードでは次のようにしています:
Logger.new("#{$ROOT_PATH}/log/errors.log", 'daily')
完全に機能していますが、2 つのファイルerrors.log.20130217
とerrors.log.20130217.1
.
1日に1つのファイルだけを強制的に作成するにはどうすればよいですか?
私はルビー標準ロガーを使用しています。毎日ローテーションしたいので、私のコードでは次のようにしています:
Logger.new("#{$ROOT_PATH}/log/errors.log", 'daily')
完全に機能していますが、2 つのファイルerrors.log.20130217
とerrors.log.20130217.1
.
1日に1つのファイルだけを強制的に作成するにはどうすればよいですか?
あなたのコードは、長時間実行されるアプリケーションに対して正しいです。
何が起こっているかというと、特定の日にコードを複数回実行しているということです。
初めて実行すると、Ruby はログ ファイル「errors.log」を作成します。
日が変わると、Ruby はファイルの名前を「errors.log.20130217」に変更します。
しかし、何らかの理由でコードを再度実行した場合、おそらく、同様のコードを使用する 2 つのアプリ (またはプロセス、ワーカー、またはスレッド) を実行しており、ロガーはファイル名 "errors.log.20130217" が既に存在することを確認しました。
ロガーはそのファイルを壊したくありませんでしたが、「errors.log」の名前を日付に変更する必要があったため、ロガーは代わりに別のファイル名「errors.log.20130217.1」を作成しました。
これを解決するには、コードを 1 回だけ実行します。
「foo」と「bar」という複数のアプリを実行している場合は、「foo-errors.log」や「bar-errors.log」などのログ ファイル名を使用します。または、複数のワーカーを使用している場合は、各ワーカーに独自のログ ファイル名を付けます (たとえば、ワーカーのプロセス ID またはワーカー プールの配列インデックスを使用するか、ワーカーを追跡します)。
本当に Ruby ロガーを使用してこれを解決したい場合は、ロガー #shift_log_period をオーバーライドして、".1" サフィックスを選択しないようにする必要があります。Logger をサブクラス化し、着用した #shift_log_period を記述して、その日付の既存のログ ファイルがあることを検出し、存在する場合は、ファイルの名前を変更する代わりにそれを使用できます。
これは、ロガーからそれを引き起こしているコードです:
def shift_log_period(period_end)
postfix = period_end.strftime("%Y%m%d") # YYYYMMDD
age_file = "#{@filename}.#{postfix}"
if FileTest.exist?(age_file)
# try to avoid filename crash caused by Timestamp change.
idx = 0
# .99 can be overridden; avoid too much file search with 'loop do'
while idx < 100
idx += 1
age_file = "#{@filename}.#{postfix}.#{idx}"
break unless FileTest.exist?(age_file)
end
end
@dev.close rescue nil
File.rename("#{@filename}", age_file)
@dev = create_logfile(@filename)
return true
複数のアプリ(別名ワーカー、プロセス、スレッド)によって同時に書き込まれたログを管理するために、ローテーターが組み込まれたRubyロガーを使用するソリューション(AFAIK)はありません。これは、各アプリが独自のログ ファイル ハンドルを取得するためです。
または、質問のコメントで Tin Man ユーザーが提案した logrotate などの優れたログ ローテーター ツールを使用します: http://linuxcommand.org/man_pages/logrotate8.html
一般に、logrotate が最善の策です。