phpのエラー表示とログについての調査
自宅のDebian9ではモジュールとして、レンタルサーバーではCGIで動いている。phpの設定は、php.ini, .htaccess, .user.ini, ユーザースクリプト(ini_set())で行うが、今回は使用状況を考えて、ユーザースクリプトで調査をする。
自宅のDebian9のパッケージになっているPHPのバージョンは次の通り
adachi@debian64:~$ php -v PHP 7.0.30-0+deb9u1 (cli) (built: Jun 14 2018 13:50:25) ( NTS ) Copyright (c) 1997-2017 The PHP Group Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies with Zend OPcache v7.0.30-0+deb9u1, Copyright (c) 1999-2017, by Zend Technologies
取得
string ini_get ( string $varname ) 成功した場合に設定オプションの値、 null 値の場合は空の文字列を返します。 その設定オプションが存在しない場合は FALSE を返します。 off という boolean の ini 値は空文字列または "0" として返されます。 一方で on の ini 値は "1" として返されます。 また、この関数はリテラル文字列で設定された INI 値を返すこともできます
値がbooleanでも返値はStringですね。
設定
string ini_set ( string $varname , string $newvalue ) 指定した設定オプションの値を設定します。 設定オプションは、スクリプトの実行中は新しい値を保持し、 スクリプト終了時に元の値へ戻されます。 成功した場合に元の値、失敗した場合に FALSE を返します。
失敗のFALSEは空の文字列のようです。
display_errors:エラーの内容をスクリプトの出力に含めるかどうか
Debian9の初期設定は ini_set('display_errors',0); (スクリプト内で同様の設定をするとしたらという意味です)
表示するようにしたければ ini_set('display_errors',1);
php.ini 中のお勧めは
; display_errors ; Default Value: On ; Development Value: On ; Production Value: Off
php.ini中の記述は: display_errors = Off
display_errors = string
ユーザースクリプトで操作してみます
echo 'initial value of display_errors is [',ini_get('display_errors'),"]\n"; echo 'type is [',gettype(ini_get('display_errors')),"]\n"; echo '===' , ini_get('display_errors')==='' ,"\n"; echo '!==' , ini_get('display_errors')!=='' ,"\n";
初期値である Off の表現は長さ0の文字列です。調べるまでもなく ini_get()の戻値は常にStringでした。
initial value of display_errors is [] type is [string] ===1 !==
===,!==の比較で得られるはずのboolean値は 1 と 長さ0の文字列 だとわかります。
setをしてみます。echo $eee は未定義の変数を参照してNoticeを発生させています。
ini_set('display_errors',0); echo 'after set 0 display_errors is [',ini_get('display_errors'),"]\n"; ini_set('display_errors',1); echo 'after set 1 display_errors is [',ini_get('display_errors'),"]\n"; echo $eee; ini_set('display_errors',"stderr"); echo 'after set 1 display_errors is [',ini_get('display_errors'),"]\n"; echo $eee; ini_set('display_errors',"Off"); echo 'after set "Off" display_errors is [',ini_get('display_errors'),"]\n"; echo $eee; ini_set('display_errors',"On"); echo 'after set "On" display_errors is [',ini_get('display_errors'),"]\n"; echo $eee; ini_set('display_errors',"0"); echo 'after set "Off" display_errors is [',ini_get('display_errors'),"]\n"; echo $eee; ini_set('display_errors',"1"); echo 'after set "On" display_errors is [',ini_get('display_errors'),"]\n"; echo $eee;
実行結果は、
after set 0 display_errors is [0] after set 1 display_errors is [1] Notice: Undefined variable: eee in /ファイルへのパス/phb001.php on line 173 after set "stderr" display_errors is [stderr] Notice: Undefined variable: eee in /ファイルへのパス/phb001.php on line 176 after set "Off" display_errors is [Off] after set "On" display_errors is [On] Notice: Undefined variable: eee in /ファイルへのパス/phb001.php on line 182 after set "0" display_errors is [0] after set "1" display_errors is [1] Notice: Undefined variable: eee in /ファイルへのパス/phb001.php on line 188
Notice:が出るので直接示すわけに行きません。ここに出したのは出力のコピーです。
ini_set()では設定された文字列がそのまま文字列として入ります。0, "0", はどちらも "0"
そして、"0", "Off", "" はerrorを表示しない
"1", "On", "stderr" は表示するということになります。
以下は実際のPHPの表示ですが、echo $eee は省いています。
initial value of display_errors is [] type is [string] ===1 !== after set 0 display_errors is [0] after set 1 display_errors is [1] after set "stderr" display_errors is [stderr] after set "Off" display_errors is [Off] after set "On" display_errors is [On] after set "0" display_errors is [0] after set "1" display_errors is [1]
true,falseについて確認します
echo "----begin----\n"; $t = true; echo $t ? "true\n" : "false\n" ; echo $t,"\n"; echo is_bool($t), "\n"; echo 'true', "\n"; echo true, True, TRUE, "\n"; echo "----true/false----\n"; $f = false; echo $f ? "true\n" : "false\n" ; echo $f,"\n"; echo is_bool($f), "\n"; echo 'false', "\n"; echo false, False, FALSE, "\n"; echo "----end------\n";
実行結果は
----begin---- true 1 1 true 111 ----true/false---- false 1 false ----end------
出力する エラーレベル
Debian9の初期設定は error_reporting(E_ALL & ~E_STRICT & ~E_DEPRECATED); (スクリプト内で同様の設定をするとしたらという意味です)
E_ALLにしたければ、error_reporting(E_ALL); または、ini_set('error_reporting', E_ALL);
php.ini 中のお勧めは
; error_reporting ; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED ; Development Value: E_ALL ; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT
php.ini中の記述は: error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
error_reporting = integer
取得と設定
int error_reporting ([ int $level ] ) 出力する PHP エラーの種類を設定する オプションの level を指定しなかった場合は、現在のエラーレベルを返す ビットマスクまたは名前つき定数で指定する error_reporting(E_ALL); は ini_set('error_reporting', E_ALL); と書いても良い
E_ERROR=1, E_WARNING=2, E_PARSE=3, E_NOTICE=8,... などとビットごとに定数が決まっている
error_reporting(E_ERROR=1 | E_WARNING=2 ) は 0b11 十進で3と指定したのと同じ。|はビット演算でOR
error_reporting(E_ALL) はすべてのビットが1である整数で、現在のバージョンで、32767。
error_reporting(E_ALL & ~E_NOTICE) は not 8 と ANDをとるので、32767-8。
echo 'type is [',gettype(ini_get('error_reporting')),"]\n"; echo 'type is [',gettype(error_reporting()),"]\n"; echo decbin(error_reporting()),':[',error_reporting(),"]: initial value\n"; echo "UDRSUUUCCCCNPWE\n"; echo decbin(E_ALL),':[',E_ALL, "]: E_ALL\n"; echo decbin(E_ALL & ~E_NOTICE),":[",(E_ALL & ~E_NOTICE),"]:(E_ALL & ~E_NOTICE)\n"; echo decbin(~E_NOTICE),": ~E_NOTICE\n";
type is [string] type is [integer] 101011111111111:[22527]: initial value UDRSUUUCCCCNPWE 111111111111111:[32767]: E_ALL 111111111110111:[32759]:(E_ALL & ~E_NOTICE) 1111111111111111111111111111111111111111111111111111111111110111: ~E_NOTICE
php.iniからくる初期値は22527。E_ALL & ~E_STRICT & ~E_DEPRECATED である。
UDRSUUUCCccNPWE
USER_DEPRECATED DEPRECATED RECOVERABLE_ERROR STRICT USER_NOTICE USER_WARNING USER_ERROR COMPILE_WARNING COMPILE_ERROR CORE_WARNING CORE_ERROR NOTICE PARSE WARNING ERROR
詳細は、
PHP マニュアル ->関数リファレンス ->PHP の振る舞いの変更 ->エラー処理 ->定義済み定数
ログに記録するかどうか。
Debian9の初期設定は ini_set('log_errors','On'); (スクリプト内で同様の設定をするとしたらという意味です)
offにしたければ、ini_set('log_errors','Off');
php.ini 中のお勧めは
; log_errors ; Default Value: Off ; Development Value: On ; Production Value: On
php.ini中の記述は: log_errors = On
log_errors = boolean
設定変更してみます。
echo 'initial value of log_errors is [',ini_get('log_errors'),"]\n"; ini_set('log_errors','Off'); echo 'initial value of log_errors is [',ini_get('log_errors'),"]\n"; ini_set('log_errors','On'); echo 'initial value of log_errors is [',ini_get('log_errors'),"]\n";
結果は
initial value of log_errors is [1] initial value of log_errors is [Off] initial value of log_errors is [On]
スクリプトエラーが記録されるファイル名。syslog が指定されると、システムのログに送られます。
Debian9の初期設定は なし
php.ini 中の記述は
; Log errors to specified file. PHP's default behavior is to leave this value ; empty. ; http://php.net/error-log ; Example: ;error_log = php_errors.log ; Log errors to syslog (Event Log on Windows). ;error_log = syslog
Debian9の初期設定は「なし」ですが、この状態でapache2のエラーログ(つまりはsyslog)に残ります。
[Sat Nov 03 13:10:46.644464 2018] [:error] [pid 5473] [client 127.0.0.1:46196] PHP Notice: Undefined variable: eee in /phpファイルへのパス/phb001.php on line 317
スクリプトによる設定では、ページの再読込でリセット(php.iniなどの設定に戻る)されるので、ページの中でerror_logファイルの設定以前のエラーは、apache2のエラーログに送られます。
設定変更してみます。
echo 'initial value of error_log is [',ini_get('error_log'),"]\n"; ini_set('error_log','../../somewhere/errlog'); echo 'initial value of error_log is [',ini_get('error_log'),"]\n";
結果は、(ここに出したのは出力のコピーです)
initial value of error_log is [] initial value of error_log is [../../somewhere/errlog]
この設定の後に起こったエラーはここに記録され、syslogには出ません。
[03-Nov-2018 13:22:12 Asia/Tokyo] PHP Notice: Undefined variable: eee in /phpファイルへのパス/phb001.php on line 346
PHP_EOL を "\n"の代わりに使うことができます。Windowsでは\nの代わりに\r\nとしてくれるとありますが、htmlでは\nのままでも問題はないので、どちらでもかまわないでしょう。
PHP_EOLは改行を表していて、環境によって自動で改行コードを切り替えてくれる。 OS 改行コード 改行コード文字 Windows CRLF \r\n Linux,Unix,MACOS10 LF \n