Pocket

こんにちは。根本です。

「fluentdのログが肥大化してしまった!」

「でも、運用を止めることが出来ない。」

という問題についてと、fluentd 自身のログのローテートについて、うまくググれなかったので備忘録。


対象 fluentd は、起動時に以下のようなオプションで起動させています。

fluentd -c config-file --log log-path -d pid-file

-cで config を指定し、 -d でデーモンとして起動しています。
pid-file には、起動したfluentdのPIDが書き込まれる)

くどいようですが、問題になっているのは、--log で指定したログファイルの肥大化です。


一応試してみましたが、fluentd を起動中にログファイルを退避しても、新しく生成されることはありませんでした。

やはり、古いファイルハンドルをつかんでいるのでしょうね。

ということで、どのようにログファイルを管理しているのかを見てみました。

目的の fluentd ソースコードは、lib/fluent/supervisor.rb になります。


47行 ~ 62行の init メソッドで、ログファイルの指定があれば、ログファイルをOpenし、Fileオブジェクトを生成。

指定がなければ、デフォルト(標準出力)の Log クラスを生成していることがわかります。

      def init
        if @path && @path != "-"
          @io = File.open(@path, "a")
          if @chuser || @chgroup
            chuid = @chuser ? Supervisor.get_etc_passwd(@chuser).uid : nil
            chgid = @chgroup ? Supervisor.get_etc_group(@chgroup).gid : nil
            File.chown(chuid, chgid, @path)
          end
        else
          @io = STDOUT
        end

        $log = Fluent::Log.new(@io, @level, @opts)
        $log.enable_color(false) if @path
        $log.enable_debug if @level <= Fluent::Log::LEVEL_DEBUG
      end

ログファイルを退避してもログファイルが生成されなかった。ということは、
ここで生成したファイルハンドルをつかんだままなのでしょう。


しかし、68行~73行の reopen! メソッドで、ログファイルを reopen しています。

      def reopen!
        if @path && @path != "-"
          @io.reopen(@path, "a")
        end
        self
      end

ということは、これを呼べばファイルハンドルを更新できるということになりますね。

では reopen! はどこで呼ばれているのかというと、

install_main_process_signal_handlers メソッドの、520行目。

      trap :USR1 do
        $log.debug "fluentd main process get SIGUSR1"
        $log.info "force flushing buffered events"
        @log.reopen!

USR1 シグナルを受け取った際に、reopen!していました。


ということは、

運用を止めずにログをローテートしたい場合には、ログを退避後に、

test -s pid-file && kill -USR1 `cat pid-file`

というように、USR1シグナルでつついてやることでOK。