Macでのsyslogの利用

はじめに

プログラム開発時のログ出力にはsyslog関数を使うと便利である。
特に、特定のターミナルと結びつかないデーモンプログラムの開発では、標準出力へのログ出力を行うことはできないため、syslogは重宝する。
ところが、このsyslogをMacで使う時は少々注意が必要だ。

syslogの出力先

Macでsyslog関数を使った場合、ログはどこに出力されるのか。
syslogの設定ファイルである "/etc/syslog.conf" を見てみる。

$ cat /etc/syslog.conf
# Note that flat file logs are now configured in /etc/asl.conf

install.* @127.0.0.1:32376

どうやら "/etc/asl.conf" で定義されているようだ。
そこで、この "/etc/asl.conf" をみてみる。

$ cat /etc/asl.conf
##
# configuration file for syslogd and aslmanager
##

# authpriv messages are root/admin readable
? [= Facility authpriv] access 0 80

# remoteauth critical, alert, and emergency messages are root/admin readable
? [= Facility remoteauth] [<= Level critical] access 0 80

# broadcast emergency messages
? [= Level emergency] broadcast

# save kernel [PID 0] and launchd [PID 1] messages
? [<= PID 1] store

# ignore "internal" facility
? [= Facility internal] ignore

# save everything from emergency to notice
? [<= Level notice] store

# Rules for /var/log/system.log
> system.log mode=0640 format=bsd rotate=seq compress file_max=5M all_max=50M
? [= Sender kernel] file system.log
? [<= Level notice] file system.log
? [= Facility auth] [<= Level info] file system.log
? [= Facility authpriv] [<= Level info] file system.log

# Facility com.apple.alf.logging gets saved in appfirewall.log
? [= Facility com.apple.alf.logging] file appfirewall.log file_max=5M all_max=50M

これを見る限り、ログの出力先は通常であれば、"/var/log/system.log" になるようだ。
そこで、

syslog(LOG_NOTICE, "%s", "test");<

というコードを書いてログを出力してみるが、一向に system.log に追記されない。

ログレベル

syslog関数のインターフェースは以下のように定義される。

void syslog(int priority, const char `message, ...);

第一引数のpriorityは、levelとfacilityの組み合わせとなっている。
ログレベルは値を持つパラメータとして以下のように定義される。

level 説明
LOG_EMERG 0 システムが使用不能
LOG_ALERT 1 速やかな復旧操作が必要
LOG_CRIT 2 重大
LOG_ERR 3 エラー
LOG_WARNING 4 渓谷
LOG_NOTICE 5 注意が必要 (デフォルト)
LOG_INFO 6 通知
LOG_DEBUG 7 デバッグレベルメッセージ

facilityは送信側のプロセスのタイプを示す。

facility 説明
LOG_AUTH セキュリティ/認証メッセージ
LOG_AUTHPRIV セキュリティ/認証メッセージ(プライベート)
LOG_CRON cronデーモン
LOG_DAEMON システムデーモン
LOG_FTP FTPデーモン
LOG_KERN カーネルメッセージ
LOG_LOCAL0(〜7) ローカルな用途
LOG_LPR ラインプリンタシステム
LOG_MAIL メールシステム
LOG_NEWS ネットワークニュースシステム
LOG_SYSLOG syslog内部で生成されたメッセージ
LOG_USER 雑多なユーザレベルのメッセージ
LOG_UUCP UUCPシステム

改めて "/etc/asl.conf" の設定を見てみると、SenderがKernelの場合はfileがsystem.logに設定されていることがわかる。
levelの設定でも、"<= notice" の場合、つまり LOG_NOTICE よりも値が小さい場合にはfileがsystem.logに設定されている。

ところが、LOG_INFOの場合は、facilityがLOG_AUTHもしくはLOG_AUTHPRIVの場合以外記載がなく、このままではsystem.logには出力されないのだ。
先ほどのコードもlevelをLOG_INFOとしたのが原因でsystem.logに出力されていなかった。

これを解決するには、まずログレベルを変更することが考えられるが、INFOレベルのログをNOTICEとして出すのは良いやり方とは言えない。
また、asl.confに設定を追記する方法が考えられるが、環境依存になってしまうのと、他のソフトウェアへの影響も考えなければならないため、こちらもあまり採用したくはない。

こういった事情を考慮すると、専用のログシステムを設けるのが一番良いのかもしれない。