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.confinstall.* @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に設定を追記する方法が考えられるが、環境依存になってしまうのと、他のソフトウェアへの影響も考えなければならないため、こちらもあまり採用したくはない。
こういった事情を考慮すると、専用のログシステムを設けるのが一番良いのかもしれない。