RHEL 中級 #5 ログ管理 — journald、rsyslog、log rotation

読了 10分

基礎 #4 で journald と journalctl を扱いました。この記事ではその上にもう 1 段入って運用でログを回す方法を整理します。保管ポリシーでディスク使用量を掴み、rsyslog でリモートサーバーにログを集め、logrotate でテキストログを自動回転させるフローまでつながります。

RHEL 中級 シリーズでこの記事の位置:

RHEL 9 のログ構造 #

RHEL 9 では 2 つのツールが一緒に働きます。journald がメイン、rsyslog がサブです。

ログフロー
   カーネル / サービス / ユーザープロセス
                │  syslog() / journald API
   ┌─────────────────────────┐
   │      journald           │   ← メイン (構造化バイナリ)
   │   /run/log/journal/     │   /var/log/journal/ (永続)
   └────────────┬────────────┘
                │ 転送 (オプション)
   ┌─────────────────────────┐
   │      rsyslog            │   ← 古いテキストログ互換 + リモート送信
   │   /var/log/messages     │
   │   /var/log/secure       │
   │   /var/log/maillog      │
   └────────────┬────────────┘
                │ logrotate (cron)
       回転された圧縮ログファイル
       /var/log/messages-20260420.gz

フローの要点:

  • カーネル・サービスが送るログはすべて journald がまず受けます。
  • journald は自分のバイナリ形式で保存しながら同時に rsyslog にも転送。
  • rsyslog は古いテキストファイル (/var/log/messages など) を作り、リモート syslog サーバーに送信することもできます。
  • すべてのテキストログファイルは logrotate が一定サイズ・期間で自動回転。

運用者は両方を知らなければなりません。新しいツールは journalctl ですが、古い資料・外部 SIEM (セキュリティ情報イベント管理)・他のホストとの統合には rsyslog が依然として必須です。

journald — 深く入る #

基礎 #4 で見た journalctl -u-b--since のようなコマンドは日常ツール。今回はその後ろの 保管ポリシーディスク使用量制御 を見ます。

揮発性 vs 永続保管 #

デフォルトの RHEL 9 は journald が 揮発性 (/run/log/journal/) で動作します。再起動すると消えます。運用マシンでは永続保管をオンにするのが標準。

永続保管をオンにする
$ sudo mkdir -p /var/log/journal
$ sudo systemd-tmpfiles --create --prefix /var/log/journal
$ sudo systemctl restart systemd-journald

# 確認
$ journalctl --list-boots
-2 ...   2026-04-18 09:01:23   2026-04-19 08:55:11
-1 ...   2026-04-19 09:00:01   2026-04-20 08:55:32
 0 ...   2026-04-20 09:00:01   2026-04-20 14:23:01

--list-boots が複数の起動を見せれば永続保管がオンになったことです。

ディスク使用量制御 — journald.conf #

永続保管をオンにするとログが無限に積もる可能性があります。上限 を明示的に掴んでおくのが運用の要点。

/etc/systemd/journald.conf 一部
[Journal]
Storage=persistent

# ディスク使用量上限
SystemMaxUse=2G
SystemKeepFree=500M
SystemMaxFileSize=128M
SystemMaxFiles=100

# 保管期間
MaxRetentionSec=30day

# 圧縮 / 封印
Compress=yes
Seal=yes

オプションの読み方:

オプション意味
Storage=persistent永続保管強制
SystemMaxUsejournald が使うディスク上限
SystemKeepFreeディスクに常に空けておく余裕
SystemMaxFileSize1 つの journal ファイルの最大サイズ (このサイズで回転)
SystemMaxFiles保管するファイル数
MaxRetentionSec保管最大期間 (30day4week1month など)
Compress自動圧縮
Seal完全性封印 (改ざん防止)

SystemMaxUseMaxRetentionSec のうち 先に到達した方 が適用されます。両方掴むのが安全。

適用 + 確認
$ sudo systemctl restart systemd-journald
$ journalctl --disk-usage
Archived and active journals take up 1.2G in the file system.

journald 整理 — 即時回収 #

急いでディスク領域が必要なとき:

強制整理
$ sudo journalctl --vacuum-size=500M     # 500M 以下に減らす
$ sudo journalctl --vacuum-time=7d       # 7 日以上経ったものを削除
$ sudo journalctl --vacuum-files=10      # ファイル 10 個に減らす

--vacuum-size が最もよく使われるオプション。運用でディスクアラート直後の即時回収が必要なときに使います。

構造化ログ活用 #

journald の本当の利点。すべてのログがキー値メタデータを持っています。

フィールド別検索
$ journalctl _COMM=sshd                       # sshd コマンドのログ
$ journalctl _SYSTEMD_UNIT=nginx.service     # 特定 unit
$ journalctl _UID=1000                        # 特定ユーザー
$ journalctl _PID=1234                        # 特定 PID

# すべてのメタデータを見る
$ journalctl -o verbose -n 5
複数条件の組み合わせ
# nginx のエラーのみ、今日
$ journalctl -u nginx -p err --since today

# 特定ユーザーが叩いた sudo コマンド
$ journalctl _COMM=sudo _UID=1000

# 特定 IP から来た ssh 試行 (メッセージ本文検索)
$ journalctl -u sshd | grep "192.168.64.50"

出力形式変更 #

JSON / その他のフォーマット
$ journalctl -o json -n 10           # 1 行 JSON
$ journalctl -o json-pretty -n 5     # 見やすい JSON
$ journalctl -o cat -n 100           # メッセージ本文のみ
$ journalctl -o short-iso -n 100     # ISO 8601 時刻

-o json は自動化に有用。jq と一緒に使うと強力な分析ツールになります。

jq との組み合わせ
$ journalctl -o json -u nginx --since today | \
    jq 'select(.PRIORITY == "3") | .MESSAGE'    # err メッセージのみ抽出

rsyslog — 古い標準が生きている理由 #

journald がメインですが rsyslog は依然として活発です。3 つの理由:

  1. 外部 SIEM (Splunk、Graylog、ELK など) 連携 — 標準の syslog プロトコルで受ける。
  2. リモートログ収集 — 複数ホストのログを 1 つのサーバーに集める。
  3. 古いテキストファイル互換/var/log/messages/var/log/secure を見る自動化 / モニタリング。
rsyslog 状態
$ systemctl status rsyslog
● rsyslog.service - System Logging Service
     Active: active (running)
     ...

主要テキストログ #

rsyslog が作るおなじみのファイルたち:

ファイル内容
/var/log/messages一般システムメッセージ
/var/log/secure認証 / 権限 (sshd、sudo など)
/var/log/maillogメール
/var/log/croncron / at ジョブ
/var/log/boot.log起動ログ
/var/log/dnf.logパッケージ作業

/var/log/secure はセキュリティ点検の最初の入口。誰がいつ ssh で接続して sudo を使ったかがすべてここに残ります。

設定 — /etc/rsyslog.conf #

/etc/rsyslog.conf 要部分
# デフォルトモジュール
module(load="imuxsock")        # local システムログを受ける
module(load="imjournal")       # journald から受ける

# ルール (facility.priority + アクション)
*.info;mail.none;authpriv.none;cron.none    /var/log/messages
authpriv.*                                   /var/log/secure
mail.*                                       -/var/log/maillog
cron.*                                       /var/log/cron
*.emerg                                      :omusrmsg:*

ルールの左側は facility.priority (どんな種類のログを)、右側は アクション (どこへ)。facility は auth/authpriv/cron/daemon/kern/mail/user/local0~7 などがあり、priority は debug/info/notice/warning/err/crit/alert/emerg

追加設定 — /etc/rsyslog.d/ #

要のファイルはそのまま置き、新しいルールは分離ファイルに置くのが標準です。

/etc/rsyslog.d/50-myapp.conf
# 私たちのアプリが使う facility local6 だけ別ファイルに
local6.*    /var/log/myapp.log
適用
$ sudo systemctl restart rsyslog

リモートログ — 複数ホスト → 中央サーバー #

運用マシンが複数台ならログを 1 か所に集めるのが標準。rsyslog がこれをします。

中央サーバー (受信側) #

/etc/rsyslog.d/00-receiver.conf
# UDP 514 で受信
module(load="imudp")
input(type="imudp" port="514")

# TCP も一緒に (安定性)
module(load="imtcp")
input(type="imtcp" port="514")

# ホスト別ディレクトリに分ける
$template RemoteHost,"/var/log/remote/%HOSTNAME%/%PROGRAMNAME%.log"
*.* ?RemoteHost
& stop
ファイアウォール / 適用
$ sudo firewall-cmd --permanent --add-port=514/udp
$ sudo firewall-cmd --permanent --add-port=514/tcp
$ sudo firewall-cmd --reload
$ sudo systemctl restart rsyslog

これで他のホストが送ったログが /var/log/remote/<hostname>/<プログラム>.log に保存されます。

クライアント (送信側) #

/etc/rsyslog.d/90-forward.conf
# すべてのログを 192.168.64.10 に転送
*.*    @192.168.64.10:514       # @ は UDP
# *.* @@192.168.64.10:514       # @@ は TCP (より安全)
適用
$ sudo systemctl restart rsyslog

TLS で暗号化 (運用推奨) #

平文 syslog はネットワークで平文で流れます。運用では TLS で包むのが標準です。rsyslog-gnutls パッケージをインストールして証明書を掴み、imrelp / omrelp モジュールを使うフローを整理します。詳細なセットアップは 上級シリーズ で扱います。

logrotate — ログ回転の標準 #

テキストログファイルはそのまま放置すると GB まで大きくなります。logrotate が一定周期・サイズに到達したら回転 (名前を変えて新しいファイルを開始) + 圧縮 + 古いものの削除を自動で。

logrotate は 独立したデーモンではなく cron または systemd timer で呼ばれる ツールです。

実行方式確認
$ systemctl list-timers | grep logrotate
NEXT  LEFT  LAST  PASSED  UNIT                  ACTIVATES
...   ...   ...   ...     logrotate.timer       logrotate.service

$ systemctl cat logrotate.timer
[Timer]
OnCalendar=daily
AccuracySec=1h
Persistent=true

毎日 1 度自動実行。古い RHEL は /etc/cron.daily/logrotate で実行しましたが RHEL 9 は systemd timer に移されました。

設定構造 #

/etc/logrotate.conf — グローバルデフォルト
weekly
rotate 4
create
dateext
include /etc/logrotate.d
/etc/logrotate.d/<package>.conf — パッケージ別ルール
# 例: /etc/logrotate.d/nginx
/var/log/nginx/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 640 nginx adm
    sharedscripts
    postrotate
        if [ -f /run/nginx.pid ]; then
            kill -USR1 $(cat /run/nginx.pid)
        fi
    endscript
}

オプションの読み方:

オプション意味
daily / weekly / monthly回転周期
rotate N保管する回転本数
compress回転直後に圧縮 (デフォルト gzip)
delaycompress回転後にもう 1 度待って圧縮 (現在使うファイル保護)
missingokファイルがなくてもエラーを出さない
notifempty空なら回転しない
create <mode> <user> <group>回転後の新ファイル生成権限
dateextファイル名に日付を付ける (-20260420)
sharedscripts複数ファイルに 1 度だけスクリプト実行
postrotateendscript回転後に実行するコマンド (シグナル送信など)

直接書く #

私のアプリのログを logrotate に任せるには:

/etc/logrotate.d/myapp
/var/log/myapp/*.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    create 640 myapp myapp
    sharedscripts
    postrotate
        systemctl reload myapp.service > /dev/null 2>&1 || true
    endscript
}

テスト / 強制実行 #

文法検査 + シミュレーション
$ sudo logrotate -d /etc/logrotate.d/myapp     # debug — どう回転されるかだけ出力
$ sudo logrotate -v /etc/logrotate.d/myapp     # verbose — 実際の実行 + 詳細出力
$ sudo logrotate -f /etc/logrotate.d/myapp     # force — 回転条件を無視して強制

運用では -d でまずシミュレーション し、意図と合えばそのまま置けばよいです。timer が自動で適用します。

journald と logrotate の関係 #

/var/log/journal/ の journald ファイルは logrotate が触りません。 journald が自分のポリシー (SystemMaxUse など) で直接回転します。

logrotate は rsyslog が作るテキストログファイル (/var/log/messages など) とユーザーが作ったログファイルを扱います。journald には logrotate、rsyslog テキストには journald が触れない 2 領域の分業。

セキュリティ / コンプライアンス観点 #

運用でよく出会う要求事項:

ログ完全性 #

Seal=yes で journald 封印をオンにするとログを改ざんすると検出されます。

検証鍵生成 + 封印確認
$ sudo journalctl --setup-keys
$ sudo journalctl --verify

保管期間ポリシー #

産業・規制に応じて異なります。よくある基準:

環境推奨保管
一般サーバー30〜90 日
PCI-DSS (決済)1 年
HIPAA (医療)6 年
金融 / SOX7 年

長期保管は通常リモートサーバーまたは S3・tape に移します。マシン内には短期のみ。

ログ無限増加防止 #

SystemMaxUseMaxRetentionSec を両方掴み、logrotate の rotate N も明示。モニタリングアラートも /var/log 使用量にかけるのが標準。

AlmaLinux / Rocky の違い #

この記事のすべてのコマンドが そのまま動作 します。journald / rsyslog / logrotate は RHEL パッケージそのまま。

よく出会う落とし穴 #

「journald 永続保管をオンにしたのにディスクが満杯になる」 #

SystemMaxUse を明示的に掴まないとデフォルトはディスクの 10% まで埋まります。大きなディスクでは問題になりえます。常に明示的に上限指定。

「journalctl が古い起動ログを見せない」 #

永続保管がオンになっていない場合。/var/log/journal/ ディレクトリがあるか確認。

「rsyslog リモートサーバーにログが来ない」 #

ファイアウォール (514 UDP/TCP) と SELinux を一緒に見てください。SELinux でポートを変えたなら syslogd_port_t が合っているか確認し、必要なら semanage port で登録する必要があります。

「logrotate が回らない」 #

systemctl status logrotate.timer で timer がアクティブか確認。または logrotate -d でシミュレーションしてどのファイルがどんな理由で回転しないか見ましょう。

「回転後にアプリが新ファイルに書かず古いファイルに書き続ける」 #

アプリが SIGHUP を受けてファイルを開き直さなければならないのに、postrotatekill -HUP または systemctl reload を抜かした場合。回転ルールに必ず reload コマンドを含めましょう。

よく使うコマンド一覧 #

ツールコマンド
journaldjournalctl -u <unit> [-f]
journaldjournalctl --since "1 hour ago"
journaldjournalctl --list-boots
journaldjournalctl --disk-usage
journaldjournalctl --vacuum-size=500M
journaldjournalctl _COMM=sshd (フィールド検索)
journaldjournalctl -o json (JSON 出力)
rsyslogsystemctl status rsyslog
rsyslogtail -f /var/log/messages
rsyslogtail -f /var/log/secure
logrotatelogrotate -d <conf> (シミュレーション)
logrotatelogrotate -f <conf> (強制実行)
logrotatesystemctl list-timers | grep logrotate

まとめ #

この記事で整理したフロー:

  • RHEL 9 のログは journald (メイン) + rsyslog (サブ) + logrotate (回転) の 3 ツールが一緒に働きます。
  • journald は永続保管 (/var/log/journal/) を明示的にオンにし、SystemMaxUse / MaxRetentionSec でディスク上限を掴むのが標準。
  • ディスクが急なときは journalctl --vacuum-size=... で即時回収。
  • 構造化ログ検索は _COMM= / _SYSTEMD_UNIT= のようなフィールド + -o json + jq の組み合わせ。
  • rsyslog は古いテキストログ互換と リモート syslog 収集 の標準。中央サーバー + クライアントのフローは 1 ホストを越える運用の日常。
  • logrotate は systemd timer で毎日実行。/etc/logrotate.d/<app> にルールを置き、-d シミュレーション で常に検証。
  • 保管ポリシーは産業・規制に応じて 30 日〜7 年、マシン外部に移すフローが一般的。

次 — ジョブスケジューリング #

ログを整理したら、次はその作業をいつ回すかへ移ります。毎日実行される logrotate 自体も systemd timer の代表的事例です。

#6 ジョブスケジューリング — cron、systemd timer、at では、伝統の cron とユーザー crontab、1 度だけ予約実行する at、マシンが切れていた時間を補う anacron、そして cron のモダンな代替である systemd timer まで — どのツールをどの状況で使うかをガイドと一緒に整理します。

X