CentOSのログ出力の仕組み (journaldとrsyslog)
CentOSのログ出力について今まで雰囲気で乗り切っていましたが、いい加減に仕組みを覚えようと思い立ち、手を動かしながら調べてみました。
Contents
CentOSのログ出力の概要
CentOSのログ出力は以下の概要図の通りです。journald
とrsyslog
が連携して動作しています。
journaldとrsyslogは、システム内に常駐するデーモンプログラムです。サービス名は、systemd-journald.service
とrsyslog.service
です。
# systemctl list-unit-files | grep -E "(systemd-journald|rsyslog)\.service"
rsyslog.service enabled
systemd-journald.service static
journald
journaldの役割
journaldは、各ソースからログを受信し、メモリ上のログデータベース(/run/log/journal/
配下)に蓄積します。設定を変更することでログデータベースの永続化もできますが、デフォルト設定ではOSをシャットダウンするとデータが消失するので、後述のrsyslogにログを転送してファイルへログを出力します。
systemdユニットプロセス
systemdのユニットファイル(/var/lib/systemd/
配下)から起動するタイプのプロセスは、同プロセスの標準出力と標準エラー出力をjournaldが収集します。systemctl
コマンドでサービスを起動したときのログは、ここで収集されます。
カーネル
カーネルのログは、一旦メモリ上のログバッファ(/dev/kmsg
)に出力されます。これは、OS起動時journaldやrsyslogが起動する前のカーネルログも保持しておく為です。
journaldは、カーネルのログバッファに蓄積したログを収集します。
一般プロセス
ユーザが起動した一般プロセスにおいて、syslog()
ライブラリコールによってログを出力した場合、journaldがログを収集します。シェルスクリプトであれば、logger
コマンドがsyslog出力によく使われます。
一般プロセスが直接ファイル出力したログについては、journaldおよびrsyslogは関与しません。
ログデータベースの閲覧
ログデータベースを直接閲覧するには、journalctl
コマンドを使用します。
以下の例では、PostgreSQLサービスを起動した後、ログデータベースの内容を表示しています。systemctl
コマンドでは何もメッセージが出力されませんが、ログデータベースの中にはsystemdユニットファイルからPostgreSQLを起動したときの標準出力が記録されています。
サービスの起動に失敗した場合は、ログデータベース内のログに失敗理由が表示されるので調査に利用できます。
# systemctl start postgresql.service
# journalctl -xe
(略)
7月 19 01:12:56 localhost.localdomain systemd[1]: Starting PostgreSQL database server...
7月 19 01:12:56 localhost.localdomain postmaster[12605]: 2020-07-19 01:12:56.539 JST [12605] LOG: starting PostgreSQL 12.1 on x86_64-redhat-linux-gnu, c>
7月 19 01:12:56 localhost.localdomain postmaster[12605]: 2020-07-19 01:12:56.540 JST [12605] LOG: listening on IPv6 address "::1", port 5432
7月 19 01:12:56 localhost.localdomain postmaster[12605]: 2020-07-19 01:12:56.540 JST [12605] LOG: listening on IPv4 address "127.0.0.1", port 5432
7月 19 01:12:56 localhost.localdomain postmaster[12605]: 2020-07-19 01:12:56.542 JST [12605] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL>
7月 19 01:12:56 localhost.localdomain postmaster[12605]: 2020-07-19 01:12:56.588 JST [12605] LOG: listening on Unix socket "/tmp/.s.PGSQL.5432"
7月 19 01:12:56 localhost.localdomain postmaster[12605]: 2020-07-19 01:12:56.688 JST [12605] LOG: redirecting log output to logging collector process
7月 19 01:12:56 localhost.localdomain postmaster[12605]: 2020-07-19 01:12:56.688 JST [12605] HINT: Future log output will appear in directory "log".
7月 19 01:12:56 localhost.localdomain systemd[1]: Started PostgreSQL database server.
なお、journalctl -u postgresql.service
のように-u
オプションで特定のサービスに関するログのみ表示することも可能です。
rsyslog
rsyslogの役割
rsyslogは、journaldのログデータベースに蓄積されたログを読み込みます。そして、ログのファシリティ(種類)とプライオリティ(優先度)に応じて、予め定義されたフォーマットで指定のファイルにログを出力します。
rsyslogの設定ファイル(/etc/rsyslog.conf
)を変更することで、外部のsyslogクライアントからsyslogを受信して統合管理したり、外部のsyslogサーバにログを転送することもできます。
ログの出力設定
以下は、rsyslog(8.37.0)のデフォルトのログ出力先設定です。<ファシリティ>.<プライオリティ>
の形式で、読み込んだsyslogをどのファイルへ出力するか定義しています。
プライオリティがemerg
のsyslogのみ、:omusrmsg:<対象ユーザ>
の形で、ビルドインモジュールを使ってログイン中の全ユーザのコンソールにメッセージを出力するよう定義しています。
# grep -vE "(^#|^$)" /etc/rsyslog.conf
(略)
*.info;mail.none;authpriv.none;cron.none /var/log/messages
authpriv.* /var/log/secure
mail.* -/var/log/maillog
cron.* /var/log/cron
*.emerg :omusrmsg:*
uucp,news.crit /var/log/spooler
local7.* /var/log/boot.log
もし、ログ出力にsyslogを使用するソフトウェアをシステムに追加する場合は、rsyslogの設定ファイルに設定行を追加します。
以下の例は、local0
のファシリティでsyslogを出力するソフトウェアのログを/var/log/sampleapp.log
に保存するよう指定しています。
local0.* /var/log/sampleapp.log
ログの出力確認
デフォルト状態で、設定通りのログがファイル出力されているか確認してみます。
# ls -l /var/log/{messages,secure,maillog,cron,spooler,boot.log}
-rw-------. 1 root root 0 7月 19 04:49 /var/log/boot.log
-rw-------. 1 root root 849 7月 19 06:01 /var/log/cron
-rw-------. 1 root root 0 7月 19 04:49 /var/log/maillog
-rw-------. 1 root root 7541 7月 19 06:20 /var/log/messages
-rw-------. 1 root root 0 7月 19 04:49 /var/log/secure
-rw-------. 1 root root 0 7月 19 04:49 /var/log/spooler
プライオリティがemerg
のsyslogをわざとローカルのjournaldに送信し、コンソールにメッセージが表示されるか確認してみます。
# logger -p local0.emerg "logging test"
#
Broadcast message from systemd-journald@localhost.localdomain (Sun 2020-07-19 06:39:57 JST):
root[12984]: logging test