本文へスキップ
設定

WordPress のデバッグログの場所: debug.log はどこにあり、どう移動するか

wp-content にある debug.log を見つけ、訪問者に取得されないよう公開ディレクトリーの外へ移し、ログが空のままになる WP_DEBUG の設定ミスを直す。

公開

WordPress はデバッグログを既定で wp-content/debug.log に書き出します。ディスク上の絶対パスにすると /path/to/your/site/wp-content/debug.log です。このファイルは何かが実際に記録されるまで存在せず、そもそも書き出されるのは wp-config.phpWP_DEBUGtrue かつ WP_DEBUG_LOG が有効になっているときだけです。そしてこの既定の場所は、実際にセキュリティ上の問題でもあります。多くのホスティングでは、誰でもブラウザーからこのファイルを取得できてしまうからです。

3 つの定数と、それぞれの役割

3 つとも wp-config.php/* That's all, stop editing! Happy blogging. */ と書かれた行より上に置きます。その行より下に書いたものは WordPress の起動が終わったあとに実行されるため、無視されます。

定数既定値役割
WP_DEBUGfalse大元のスイッチ。PHP のエラー報告レベルを上げ、notice・warning・非推奨の警告を出す。これがないと以下は何も動かない。
WP_DEBUG_LOGfalseエラーをファイルに出力する。true なら wp-content/debug.log。文字列を渡すと書き出し先のファイルパスとして扱われる。
WP_DEBUG_DISPLAYtrueエラーをページの HTML に出力する。すべての訪問者に見える。

みんなが間違えるのは依存関係です。WP_DEBUG_LOG は WordPress の起動処理のうち WP_DEBUG の分岐の中で読まれます。WP_DEBUGfalse なら、WP_DEBUG_LOGtrue にしても何も起きません。ファイルも作られず、エラーも警告も出ません。WP_DEBUG_LOG を追加したのにログが現れないなら、まず WP_DEBUG を確認してください。

公開サイトで機能する設定はこうです。

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
@ini_set( 'display_errors', 0 );

WP_DEBUG がファイルの上のほうですでに定義されているなら(たいていは false で定義されています)、2 つめの define() を足すのではなく、その既存の行を書き換えてください。同じ定数を二重に定義すると PHP の warning が出ますし、表示が有効なサイトではそれがページの一番上に出てきます。

本番で WP_DEBUG_DISPLAY を false にすべき理由

表示を有効にすると、PHP のエラーは HTML レスポンスの中に出力されます。テーマから出る非推奨の警告 1 つで、サーバー上の絶対パスが全訪問者に見えます。データベースのエラーならテーブル名とクエリの断片が出ます。さらに悪いことに、ヘッダー送信より前に出力が発生するとリダイレクトが壊れ、きれいな JSON を期待している REST や AJAX のレスポンスも壊れ、結果として「プラグインのせいだ」と誤解されがちな白い画面を生みます。

知っておく価値のある細かい話がひとつ。WP_DEBUG_DISPLAYnull にするのは false と同じではありません。null は「PHP の display_errors の設定には触れず、サーバーの設定をそのまま引き継ぐ」という指示です。false は積極的にオフへ倒します。本番サイトでは false を使い、さらに保険として上の ini_set の行も入れておいてください。プラグインがリクエストの後半で display_errors を戻してしまうことがあるためです。

既定の場所は外から取得できる

wp-content/debug.log は公開ディレクトリーの中にあります。素の WordPress には、このファイルへの直接アクセスを遮断する仕組みは入っていません。よくある Apache や nginx の構成では、https://yoursite.com/wp-content/debug.log を開くとプレーンテキストとしてファイルが返ってきます。デバッグログにはサーバーの絶対パス、プラグインやテーマの内部構造、実際のクエリ文字列を含むデータベースエラー、ときには失敗した関数に渡された値まで入っています。URL を当てた相手にとってはタダの偵察材料で、しかもここは自動スキャナーが真っ先に試す URL のひとつです。

対処は 2 通りあります。よいのはログを移すほうです。

パスを指定してログを移す

WordPress 5.1 以降、WP_DEBUG_LOG は真偽値の代わりに文字列のファイルパスを受け取れます。ドキュメントルートの外を指定してください。

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', '/home/youruser/logs/wp-errors.log' );
define( 'WP_DEBUG_DISPLAY', false );

このパスには 3 つのルールがあります。絶対パス を使うこと。相対パスは PHP の作業ディレクトリーを基準に解決され、それはリクエストごとにもサーバーごとにも変わるので、ファイルの行方がわからなくなります。ディレクトリーは事前に存在していること。PHP は作ってくれませんし、ファイルを開けなければ何も言わずに失敗します。そして PHP のユーザーが書き込めること。共有ホスティングでは、これは SFTP でログインするアカウントとは別です。

ホスティングの都合で公開ディレクトリーの中しか使えず、その上に書き込める場所がない場合は、既定のパスのままにして、サーバー側でアクセスを遮断します。Apache なら次のとおりです。

<Files "debug.log">
  Require all denied
</Files>

これはルートではなく wp-content の中の .htaccess に置いてください。ルートの .htaccess はパーマリンクを保存したときに WordPress が書き換えるので、追記した内容が消えることがあります。nginx では .htaccess はまったく機能しません。サーバー設定に location ブロックが必要で、マネージドホスティングではたいていサポートに依頼することになります。

遮断で得られるものについては正直でいましょう。ファイルは依然として、Web サーバーが配信するディレクトリーの中にディスクとして存在しています。どれかのプラグインにパストラバーサルの脆弱性があれば、そこから読めます。公開ディレクトリーの外へ移すほうが、対策としては強いです。

ファイルを読む・追いかける

SSH が使えるなら、バグを再現しながらリアルタイムで眺められます。

tail -f wp-content/debug.log

別のタブでエラーを再現すると、書き込まれた行がその場で流れてきます。最近の分だけを見たい、あるいは特定のプラグインで絞り込みたい場合はこうです。

tail -n 100 wp-content/debug.log
grep -i 'plugin-slug' wp-content/debug.log | tail -n 50

PHP はファイルの末尾に追記するので、下から上へ読んでください。各行のタイムスタンプは UTC で、WordPress のタイムゾーン設定とは一致しません。古い行を見ていると勘違いしないように注意してください。

WP-CLI を使えば、ファイルを手で編集せずに定数を切り替えられます。

wp config set WP_DEBUG true --raw
wp config set WP_DEBUG_LOG true --raw
wp config set WP_DEBUG_DISPLAY false --raw

--raw フラグが重要です。これがないと、真偽値ではなく "true" という文字列として書き込まれます。パスを指定する形式のときは、引用符付きの文字列として書き込ませたいので --raw は外してください。

SSH がない場合は、SFTP でファイルをダウンロードするか、ホスティングのファイルマネージャーで開きます。ログを wp-admin の中で見せてくれるプラグインは、完全に信頼できる場合を除いて避けてください。サーバー内部の情報だらけのファイルへの読み取り権限を、そのプラグインに渡すことになります。

自分の環境に合わせた wp-config のブロックが欲しい場合は、公開ディレクトリー外の安全なパスと対応するサーバー設定も含めて、WordPress デバッグログ生成ツール が作ってくれます。

終わったら必ずオフに戻す

WordPress のコアには debug.log をローテーションしたり切り詰めたりする仕組みがありません。ページを読み込むたびに notice が出るようなサイトでは、ファイルは際限なく大きくなり、ディスクを埋めます。そうなると、追いかけていたバグよりひどい形でサイトが落ちます。ログを有効にして、問題を再現して、ログを読んで、WP_DEBUGfalse に戻す。この順番です。

ファイルを削除せずに中身だけ空にするには、次のようにします。

: > wp-content/debug.log

ログが空のままのとき

上から順に確認してください。WP_DEBUGfalse — 最も多い原因で、しかも何も言わずに他のすべてを無効化します。定数が「編集を終わり」の行より下にあるwp-config.php の位置を確認します。パーミッション — PHP が wp-content、または指定したディレクトリーに書き込めていません。wp-config の読み込みが終わる前の致命的エラー — 設定ファイル自体の構文エラーなどは、WordPress のログ機能が動き出すより早く起きるため、サーバー自身の PHP エラーログのほうに出ます。ホスティングによる上書き — 一部のマネージド環境は PHP の error_log 設定を固定していたり、ログを独自のダッシュボードへ流していたりします。この場合、あなたの定数の設定は正しく、出力先が別の場所にあるだけです。設定が壊れていると決めつける前に、ホスティングのログビューアーを確認してください。

FAQ

よくある質問

WordPress のデバッグログはどこにありますか?

既定では wp-content フォルダーの直下、wp-content/debug.log です。WordPress は実際にエラーが記録された時点で初めてこのファイルを作るので、wp-content に見当たらないからといってログ出力が壊れているとは限りません。WP_DEBUG_LOG に true ではなくファイルパスを指定している場合は、そのパスに書き出されます。

wp-content に debug.log がないのはなぜですか?

よくある理由は 3 つです。WP_DEBUG が false になっていて、WP_DEBUG_LOG が何であろうとログ出力自体が有効にならない。まだ何もエラーが起きておらず、ファイルが作られていない。あるいはパーミッションの問題で PHP が wp-content に書き込めない。まず定数を、次にパーミッションを確認してください。

WordPress の debug.log は誰でもダウンロードできてしまいますか?

たいていはできてしまいます。wp-content/debug.log は公開ディレクトリーの中にあり、アクセスを制限する設定も標準では入っていないため、その URL をブラウザーで開くとファイルが返ってくることがよくあります。デバッグログにはサーバーの絶対パス、データベースのエラー、クエリの断片が普通に含まれます。公開ディレクトリーの外へ移すか、サーバー設定でアクセスを遮断してください。

WP_DEBUG_LOG と WP_DEBUG_DISPLAY の違いは何ですか?

WP_DEBUG_LOG はエラーをファイルに書き出します。WP_DEBUG_DISPLAY はエラーをページの HTML に出力するため、訪問者にも読まれます。公開サイトではログはオン、表示はオフが正解です。そしてどちらも、WP_DEBUG が true でない限り完全に無視されます。ここが一番見落とされる点です。

WordPress のデバッグログはどうやって読みますか?

SSH が使えるなら、ログのパスに対して tail -f を実行し、問題を再現しながら新しい行が出てくるのを眺めるのが一番です。SSH がなければ SFTP でダウンロードするか、ホスティングのファイルマネージャーで開きます。PHP は新しい行を末尾に追記していくので、下から上へ読んでください。

WP_DEBUG を有効にすると公開サイトは遅くなりますか?

多少は遅くなりますが、より大きなリスクはディスクです。アクセスの多いサイトで詳細なログを出し続けると debug.log が数ギガバイトに膨らみ、ディスクを埋めてサイトを落とします。有効にして、バグを再現して、ログを読んで、また無効に戻す。WordPress のコアには、このファイルをローテーションしたり切り詰めたりする仕組みはありません。