理系学生日記

おまえはいつまで学生気分なのか

rsyslogで動的なファイル名を使用する

ここ数日、rsyslog について調べていました。 恥ずかしながら、rsyslog は導入・構築するシステムに入っていることは多かったのですが、それでもきちんと学んだことは無かったので、この際だからきちんと学んでみようと。

今日はそんな中で、動的なログファイル名の設定方法です。

答え

以下の順で設定すれば良いです。

  1. 動的ファイル名用のテンプレートを定義する
  2. セレクタの行の Action 部分に、? 付きでテンプレート名を指定する

以下は、facility、severity に関わらず、ログ転送元のホストに応じてログファイルを分割するときの例です。

rsyslog では、色々な設定フォーマットがあって分かりづらいのですが、利用が推奨されている RainerScript 形式で記述すると以下のようになります。

template (name="DynFile" type="string" string="/var/log/system-%HOSTNAME%.log")
*.* ?DynFile

もはや公式からは利用すんなって言われている、Legacy Configuration 形式で指定するとこんなかんじ。 だいたい $ が付く形式は Legacy です。

$template DynFile,"/var/log/system-%HOSTNAME%.log"
*.* ?DynFile

他にも、ログを年・月・日・ホスト名で切り換えるテンプレートは以下のようになります。

template(name="DailyPerHostLogs" type="string"
    string="/var/log/syslog/%$YEAR%/%$MONTH%/%$DAY%/%HOSTNAME%/messages.log"
)
*.* ?DailyPerHostLogs

ロギングを行うアプリケーションの info ログのファイルを分ける場合は、こんなかんじですね。

template(name="AppLogs" type="string" string="/var/log/%HOSTNAME%/%programname%.log")
*.=info ?AppLogs

なにをやっているのか

これらが何をやっているのかってのが結構読み解くのがつらいんですが、おそらく必要な知識は、「template」と「action」だと思います。

Template

rsyslog における template は、言ってみればログのフォーマットを決定するものです。また、ログ「ファイル」に限定されず、例えば MySQL や Postgresql にログを保存するときの形式も含まれます。ログする内容を規定するのに使われるのが、基本的な利用方法かと思います。 動的にファイル名を変更するのは、どちらかというと「基本」ではないという印象。

「いや、rsyslog 使ってるけど、template なんぞ見たことない」という人も多いと思いますが、CentOS 7.4、rsyslog 8.24 という環境で、rsyslog.cong を見ると、デフォルトで RSYSLOG_TraditionalFileFormat というテンプレートが指定されていることがわかります。

$ cat /etc/redhat-release; rpm -qa | grep rsyslog; grep -i template /etc/rsyslog.conf
CentOS Linux release 7.4.1708 (Core)
rsyslog-8.24.0-12.el7.x86_64
$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat

rsyslog.conf を書くときに、何も意識しない場合、このテンプレートが適用されます。例えば以下の例の /var/log/messages 等のフォーマット等ですね。

$ grep /var/log/messages /etc/rsyslog.conf
*.info;mail.none;authpriv.none;cron.none                /var/log/messages

一応ですが、この RSYSLOG_TraditionalFileFormat は以下のように定義されているようです。この定義は Legacy Configuration で定義していますが、公式では今後は RainerScript 形式での定義を推奨しています。

$template FileFormat,"%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n"

じゃぁ本筋の RainerScript 形式だとどうかっていうと、こんなかんじ。うーん分かりやすくなったのかどうか。。。

# 馬鹿正直に書き下す場合
template(name="FileFormat" type="list") {
    property(name="timestamp" dateFormat="rfc3339")
    constant(value=" ")
    property(name="hostname")
    constant(value=" ")
    property(name="syslogtag")
    property(name="msg" spifno1stsp="on" )
    property(name="msg" droplastlf="on" )
    constant(value="\n")
}

# Legacy Configuration 形式と歩調を合わせる場合
template(name="tpl3" type="string"
     string="%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n"
)

設定内容については、なんとなく読み解けるかと思いますが、興味のある方はこちらをご参照頂ければと…。

動的ファイル名のテンプレート

ファイル名のテンプレートについては、ここにチョロっと書いてあるのですが、type=string で定義するようです。

再掲しますが、転送元ホスト名でファイル名を切り替えるテンプレートは以下のようになりますし、

template (name="DynFile" type="string" string="/var/log/system-%HOSTNAME%.log")

ログを年・月・日・ホスト名で切り換えるテンプレートは以下のようになります。

template(name="DailyPerHostLogs" type="String"
    string="/var/log/syslog/%$YEAR%/%$MONTH%/%$DAY%/%HOSTNAME%/messages.log"
)

必要なディレクトリは、rsyslog が勝手に作ってくれます。先回りしてディレクトリを作成しておく必要はありません。もちろん、不要になったディレクトリを削除してはくれませんので、そのあたりのハウスキーピングの仕組みは別途構築する必要があります。

テンプレートの適用

テンプレートの適用については、Action という概念で説明されます。Action という言葉に馴染みがない人もいるかもしれませんが、以下の /var/log/secure とか、root とかの指定が Action です。 どのメッセージに対して「何を行うか」ってことですね。

# facility が authpriv のメッセージは、/var/log/secure に出力
authpriv.*                                              /var/log/secure
# critical なメッセージがあれば、root に通知
*.=crit root

通常、ログファイル名を指定すれば、そこにメッセージのログを吐いてくれるのですが、その「ログファイル名」自体が動的になる場合は ? というプレフィックスを付けて、テンプレート名を指定します。

authpriv.*   ?DailyPerHostLogs

という感じですね。

参考文献