2026年7月27日

2026年7月27日

rsyslogのカスタム設定|ログの振り分け・転送・ローテーションの書き方

rsyslogでアプリケーションのログを専用ファイルに分けたり、別サーバーへ転送したりするには、/etc/rsyslog.d/ に番号付きの設定ファイルを追加し、条件と出力先(アクション)を書くのが基本です。この記事では、RainerScript形式と従来形式の両方の書き方、ファイルの読み込み順と stop の使い方、TCPでの転送と受信、logrotateとの連携までを、設定を壊さずに確認しながら進める手順として説明します。対象はUbuntu/DebianとRHEL系で標準のrsyslog v8です(2026年10月現在)。

設定ファイルの場所と読み込み順

メインの設定は /etc/rsyslog.conf ですが、直接編集するより /etc/rsyslog.d/ に .conf ファイルを追加するほうが、パッケージ更新時に設定が上書きされる心配がなく管理しやすくなります。rsyslog.conf の中に $IncludeConfig /etc/rsyslog.d/*.conf または include(file="/etc/rsyslog.d/*.conf") があり、ここで追加ファイルが名前順に読み込まれます。

名前順という点が重要です。Ubuntuでは標準のルールが /etc/rsyslog.d/50-default.conf に書かれていて、/var/log/syslog へ書き出す設定もここにあります。自分の振り分けルールを 30-myapp.conf のように50より小さい番号で作り、最後に stop を書けば、そのログは標準ルールに届く前に処理が終わり、/var/log/syslog との二重記録を防げます。逆に 60-myapp.conf にすると、先に標準ルールで記録された後で自分のルールが動きます。RHEL系では標準ルールが rsyslog.conf 本体に書かれているため、追加ファイルの読み込み位置を本体で確認しておきます。

ファシリティと重要度の基本

syslogのメッセージには、送信元の種類を表すファシリティ(auth、cron、daemon、mail、local0〜local7 など)と、重要度を表すプライオリティ(emerg、alert、crit、err、warning、notice、info、debug)が付いています。独自のアプリケーションには、ほかで使われていない local0〜local7 のどれかを割り当てるのが一般的です。

ただし最近のアプリケーションは、ファシリティを指定せずに標準出力へログを出し、systemdのjournald経由でrsyslogに届くことも多くあります。この場合はファシリティで分けるより、プログラム名($programname)で分けるほうが取りこぼしを減らせます。

従来形式で振り分ける

古くから使われている形式は「セレクター 出力先」を1行で書きます。短く書ける反面、細かい指定はしにくい形式です。

# /etc/rsyslog.d/30-local0.conf
# local0 の info 以上を専用ファイルへ
local0.info    /var/log/local0.log
& stop

# プログラム名が myapp のメッセージを専用ファイルへ(プロパティフィルター)
:programname, isequal, "myapp"    /var/log/myapp/myapp.log
& stop

& は直前の条件をそのまま引き継いで次のアクションを実行する記号で、& stop は「この条件に一致したメッセージはここで処理を終える」という意味になります。古い資料にある & ~ も同じ意味ですが、v8では非推奨の書き方です。

RainerScript形式で振り分ける

v6以降で使えるRainerScript形式は、if による条件分岐と、パラメーター付きの action() で書きます。出力ファイルの所有者や作成時の権限まで指定できるので、新しく書く設定はこちらがおすすめです。

# /etc/rsyslog.d/30-myapp.conf
if $programname == 'myapp' then {
    action(
        type="omfile"
        file="/var/log/myapp/myapp.log"
        template="RSYSLOG_FileFormat"
        createDirs="on"
        fileCreateMode="0640"
        dirCreateMode="0755"
    )
    stop
}

# 重要度が err 以上(数値 3 以下)のメッセージを別ファイルにも残す
if $syslogseverity <= 3 then {
    action(type="omfile" file="/var/log/errors.log")
}

template="RSYSLOG_FileFormat" は組み込みのテンプレートで、日時をタイムゾーン付きの高精度な形式で記録します。ディストリビューションの設定によっては、指定しない場合に従来の Oct 17 10:00:00 形式になります。従来形式は年が入らないため長期保存するログでは不便で、明示しておけば環境による差も出ません。

つまずきやすいのはファイルの作成権限です。Ubuntu/Debianのrsyslogは起動後に syslog ユーザーへ権限を落として動くため、/var/log/myapp/ を root だけが書き込める状態で作ってしまうと、ファイルを作成できずにログが記録されません。事前にディレクトリを作るなら、所有者をrsyslogの実行ユーザーに合わせます。

# Ubuntu/Debian の場合(RHEL系は root で動くため不要なことが多い)
sudo install -d -o syslog -g adm -m 0755 /var/log/myapp

設定の検証と動作確認

設定を書いたら、再起動の前に構文を検証します。誤りがあるまま再起動すると、その行が無視されたり、rsyslogが起動しなかったりして、ログが記録されない時間が生まれます。

# 構文チェック(エラーがなければ終了コード 0)
sudo rsyslogd -N1

# 反映
sudo systemctl restart rsyslog

# テストメッセージを送る(-t でタグ=プログラム名、-p でファシリティ.重要度)
logger -t myapp "rsyslog test from myapp"
logger -p local0.info "rsyslog test via local0"

# 振り分け先と、syslog に二重記録されていないかを確認
sudo tail -n 3 /var/log/myapp/myapp.log
sudo grep -c "rsyslog test from myapp" /var/log/syslog

/var/log/syslog 側の件数が0なら stop が効いています。RHEL系では標準の出力先が /var/log/messages なので、そちらを確認します。記録されないときは journalctl -u rsyslog でrsyslog自身のエラー(権限不足など)が出ていないかを見ます。

別サーバーへ転送する

ログを集約サーバーに送ると、サーバーが侵害されたりディスクが壊れたりしても記録が手元に残ります。送信側では、転送先が停止していてもログを失わないように、ディスクを使うキューを設定しておきます。

# 送信側 /etc/rsyslog.d/60-forward.conf
# 192.0.2.10 は例。集約サーバーのアドレスに置き換える
*.* action(
    type="omfwd"
    target="192.0.2.10"
    port="514"
    protocol="tcp"
    queue.type="LinkedList"
    queue.filename="fwd_central"
    queue.maxDiskSpace="1g"
    queue.saveOnShutdown="on"
    action.resumeRetryCount="-1"
)

queue.filename を指定すると、メモリーに収まらない分や停止時の未送信分が作業ディレクトリ(rsyslog.conf の $WorkDirectory または global(workDirectory="...") で指定された場所)に保存されます。action.resumeRetryCount="-1" は再送を無期限に続ける設定です。UDPで送る場合は protocol="udp" にしますが、UDPは届いたかどうかを確認しないため、ネットワークが混雑するとログが欠けます。

受信側では、TCPの受信モジュールを読み込み、受け取ったログをホスト別のファイルに書き分けます。ruleset を使うと、受信したログをローカルのログと混ぜずに処理できます。

# 受信側 /etc/rsyslog.d/10-receive.conf
module(load="imtcp")

template(name="RemotePerHost" type="string"
         string="/var/log/remote/%HOSTNAME%/%PROGRAMNAME%.log")

ruleset(name="remote") {
    action(type="omfile" dynaFile="RemotePerHost" createDirs="on")
}

input(type="imtcp" port="514" ruleset="remote")

受信側のファイアウォールでは、514番ポートを送信元サーバーのIPアドレスだけに開けます。インターネット越しに送る場合、平文のTCPでは内容が読まれる可能性があるため、TLSで暗号化するか、VPNなどの閉じた経路を使ってください。

logrotateと連携する

振り分けたログファイルは、logrotateで定期的に切り替えて古いものを圧縮・削除します。rsyslog v8は、HUPシグナルを受け取ると開いているファイルを閉じて開き直すため、ローテーション後にHUPを送るのが定番です。なお、HUPでは設定の再読み込みは行われないので、設定を変えたときは再起動が必要です。

# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
    daily
    rotate 14
    missingok
    notifempty
    compress
    delaycompress
    sharedscripts
    postrotate
        /usr/bin/systemctl kill -s HUP rsyslog.service >/dev/null 2>&1 || true
    endscript
}

この例では毎日切り替え、14世代を残し、1つ前の世代は圧縮せずに残します(delaycompress)。sharedscripts を付けているので、複数のファイルが対象でもHUPは1回だけ送られます。systemctl のパスは command -v systemctl で確認してください。

設定後は、実際には何も変更しない確認モードで動作を見てから、強制実行で試します。

# 何が起きるかを表示するだけ(変更しない)
sudo logrotate -d /etc/logrotate.d/myapp

# 強制的に1回ローテーションして結果を確認
sudo logrotate -f /etc/logrotate.d/myapp
ls -l /var/log/myapp/

「parent directory has insecure permissions」と表示される場合は、ディレクトリがグループや他者から書き込める状態になっています。権限を 0755 にするか、設定に su syslog adm のように実行ユーザーを指定します。

まとめ

  • 追加の設定は /etc/rsyslog.d/ に番号付きで置く。標準ルールより小さい番号にして stop を書くと、二重記録を防げる
  • 新しく書くならRainerScript形式。$programname での振り分けはjournald経由のログも拾いやすい
  • Ubuntu/Debianではrsyslogが syslog ユーザーで動くため、出力先ディレクトリの所有者に注意する
  • 再起動前に rsyslogd -N1 で構文を確かめ、logger で振り分けを確認する
  • 転送はTCPとディスクキューで取りこぼしを減らし、logrotateではHUPを送ってファイルを開き直させる

お気軽にご相談ください

お見積りへ お問い合わせへ
▲