PHPのerror_logをsyslogに設定したら文字化け(FreeBSD固有の問題だった)
PHPでバッチ処理を書いているときの覚書。
環境: FreeBSD 14.1-RELEASE-p6, PHP 8.3.6
PHPエラーはシステムログに設定する。
# php --ini
# less /usr/local/etc/php.ini
error_log = syslog
これで「/var/log/messages」に出力されるようになる。
PHPエラー時に確認してみると文字化けしている。
# less /var/log/messages
文字コードの確認。
# less /usr/local/etc/php.ini
default_charset = "UTF-8"
UTF-8になっている。
システムの言語設定を表示。
# locale
LANG=C.UTF-8LC_CTYPE="C.UTF-8"LC_COLLATE="C.UTF-8"LC_TIME="C.UTF-8"LC_NUMERIC="C.UTF-8"LC_MONETARY="C.UTF-8"LC_MESSAGES="C.UTF-8"LC_ALL=
各説明は下記サイトを参考に。
参考: ロケール環境変数について - IBM Documentation
これを日本語に設定すればいいのかな?
設定できるlocale一覧を表示。
# locale -a
FreeBSDは/etc/login.confを編集する。
参考: Chapter 25. Localization - i18n/L10n Usage and Setup | FreeBSD Documentation Portal
# less /etc/login.conf
default:\...:charset=UTF-8:\:lang=ja_JP.UTF-8:
/etc/login.confを編集したときはcapability databaseを更新する必要があるみたい。
# cap_mkdb /etc/login.conf
一旦ログインしなおして確認。
# locale
LANG=ja_JP.UTF-8LC_CTYPE="ja_JP.UTF-8"LC_COLLATE="ja_JP.UTF-8"LC_TIME="ja_JP.UTF-8"LC_NUMERIC="ja_JP.UTF-8"LC_MONETARY="ja_JP.UTF-8"LC_MESSAGES="ja_JP.UTF-8"LC_ALL=
ja_JP.UTF-8になった。
PHPでエラーを起こして確認。
# tail -f /var/log/messages
文字化けしている…。
syslogを再起動してみる。
サービス名を確認して再起動。
# service -l
# service restart syslogd
restart does not exist in /etc/rc.d or the local startupdirectories (/usr/local/etc/rc.d), or is not executable
rc.dを直接実行する。
# /etc/rc.d/syslogd restart
PHPでエラーを起こして確認。
# tail -f /var/log/messages
文字化けしている…。
Google AI Studioで聞いてみた。
Model: Gemini 1.5 Pro
例えば下記のような文字化けになっています。なぜこのような文字化けとなるか分かりますか?
---
Dec 9 10:10:45 vm-dev2 php[1202]: PHP 6. wp_trigger_error($function_name = '', $message = '<E9>M-^V<A2><E6>M-^U<B0>...
AIの回答。
この文字化けは、UTF-8 でエンコードされた日本語が、ISO-2022-JP として誤って解釈されているために発生しています。
すごい。
具体的な解決策も提示してくれる。
正しいかどうか疑問に思いながらも提示通りに修正してみる。
# less /etc/syslog.conf
# Add this line!*.* ;encoding(utf-8)
syslogdを再起動。
# /etc/rc.d/syslogd restart
AIの提案で知ったloggerコマンドで直接エラーを起こす。
# logger -t test 'test日本語test'
確認
# less /var/log/messages
文字化けしている…。
PHPの設定とは関係ないことは分かった。
AIの提案で知ったsyslogdをdebugモードで起動する方法を試す。
# /etc/rc.d/syslogd stop
# syslogd -d
loggerコマンドで直接エラーを起こす。
# logger -t test 'test日本語test'
そしてAIに聞いてみた。
デバッグログの出力 test�M-^W��M-^\��M-^^test から、syslogd はメッセージを UTF-8 として正しく受信しているものの、何らかの理由で表示時に文字化けが発生していることが分かります。 � は、無効なバイトシーケンスを表す置換文字です。 M-^W などは、UTF-8 のマルチバイト文字の一部が誤って解釈されていることを示唆しています。この状況では、syslogd の出力先の設定、またはコンソール自体の設定に問題がある可能性が高いです。
UTF-8のPHPファイルをlessで表示しても問題ないので、コンソールは問題ないと思う。
出力先ファイルのエンコーディング確認。
# file /var/log/messages
/var/log/messages: ISO-8859 text, with very long lines (1708)
syslogd が UTF-8を受け取ったのをISO-2022-JPに変換している。
つまりsyslogdのバグかな?
ここでCentOS Stream 9でloggerを実行してみた。
# logger -t test 'test日本語test'
# less /var/log/messages
文字化けしてない!
ということでFreeBSDのsyslog固有の問題です。
バッチログはファイルに出力することにした。