skills/wordpress-triage/references/DECISION-TREE.md
Workspace snapshot · 09/04 13:33
症状別 切り分けツリー(T1〜T8)
SKILL.md Step 2 で分類したあと、該当する節だけを読む。
各節は「先に確認すること」→「原因候補」→「確認コマンド」の順で、上から潰す。
共通の前提: SKILL.md Step 1 の証拠保全が終わっていること。
T0. どのツリーへ入る前にも: 障害ではない401/403を先に外す
「サイトが見られない」の相談で、そもそも壊れていないことがある。 レンタルサーバーでは次の2つが同じ見え方をする。
| 返る | 疑うもの | 確かめ方 |
|---|---|---|
| 401 | Basic認証が生きている(ステージングの残骸、または意図的な制限) | curl -sI "$(wp option get home)" の WWW-Authenticate ヘッダー。認証を通すと200になるなら障害ではない |
| 403 | WAF、IP制限、.htaccess の Deny、パーミッション | WAFを一時停止できる環境なら止めて再確認。止めて直るならWAF。 止められないならホスティングのWAFログを見る |
これを先に外さないと、切り分け全体が誤る。 「更新したら403になった」でロールバックしても、 WAFが原因なら直らない。戻したのに直らない、が一番時間を溶かす。
なお wp コマンド自体はHTTPを経由しないので、ブラウザが403でも wp は動く。
この非対称は切り分けに使える——wp が動いてブラウザだけ403なら、
WordPressではなくWebサーバー層を見る。
T1. 実行時エラー(真っ白 / 500 / Fatal error)
先に確認すること
- 直前に何をしたか(更新/PHP変更/プラグイン追加/移行)。「何もしていない」なら自動更新を疑う。
- 管理画面も落ちているか、フロントだけか。管理画面が生きているなら切り分けは格段に楽。
原因候補(頻度順)
- プラグイン/テーマのPHP致命的エラー ログの1行目にファイル名と行番号が出る。そこを読む。
- PHPバージョン差異
移行やサーバー側の変更でPHPが上がり、古いコードが動かなくなった。
→ PHPを元のバージョンへ戻して復旧させる。 PHP更新は障害対応と切り離し、別作業にする。
CLIのPHPとWebのPHPはバージョンが違うことがある。 事業者の管理画面で確認する。php -v wp eval 'echo PHP_VERSION;' # WordPressが読んでいるPHP(CLIと違うことがある) - メモリ不足
define('WP_MEMORY_LIMIT', '256M');php.iniのmemory_limitも見る。ログにAllowed memory size ... exhaustedが出る。 - キャッシュ系ドロップインの残骸
キャッシュプラグインを消したのに
wp-content/advanced-cache.php/object-cache.phpが残っている。 → 両ファイルを退避する(削除ではなく退避)。 .htaccessの持ち込み / 不正ディレクティブ Apache→Nginx、または事業者固有の記述。 → 退避してwp rewrite flush --hardで標準を再生成。- ディスク容量・inode枯渇
見落とされやすい。書き込めないだけで多様な症状が出る。df -h . ; df -i .
管理画面も入れない場合の順序
wp-config.phpでデバッグログを有効化(WP_DEBUG_DISPLAYは false)- ログを読む → 原因が読めたらそのプラグイン1つを停止
- 読めない場合のみ、有効一覧を保存してから全停止 → 1つずつ有効化
T2. データベース接続確立エラー
原因は4つしかない(SKILL.md Step 4)。ここでは確認の詳細だけ。
wp db check # 接続できるか
wp db tables # テーブルが見えるか
wp config get DB_HOST --type=constant
wp config get DB_NAME --type=constant
- 接続できるがテーブルが見えない →
$table_prefix不一致。「インストール画面」が出るのはこれ。 - 接続自体ができない → 認証情報かDBサーバー側。
何も変更していないのに起きたなら、事業者の障害情報を先に見る。
接続数上限(
Too many connections)は、こちらの設定では直らない。 wp-config.phpを編集する前に、必ず元のファイルをコピーして残す。
T3. リダイレクトループ
curl -sIL https://example.com | grep -iE '^(HTTP|location)'
1. siteurl / home の不整合
wp option get siteurl ; wp option get home
違っていれば揃える。移行直後はここが最有力。
wp option update siteurl 'https://example.com'
wp option update home 'https://example.com'
2. 定数がDBを上書きしている
wp config get WP_SITEURL --type=constant
wp config get WP_HOME --type=constant
定数がある限り、DBの値を直しても効かない。「直したのに変わらない」の典型。
3. リバースプロキシ + HTTPS強制
プロキシがバックエンドへHTTPで渡しているのに、WordPress側がHTTPSを強制して往復する。
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
$_SERVER['HTTPS'] = 'on';
}
wp-config.php の require_once ABSPATH . 'wp-settings.php'; より前に置く。
4. 二重リダイレクト
.htaccess/Nginx側の常時SSL・www正規化と、プラグイン側の同じ設定が両方効いている。
→ どちらか片方に統一する。 両方消してから片方だけ戻すのが早い。
T4. トップは出るが下層が全部404
パーマリンクのリライトが効いていない。
wp rewrite structure '/%postname%/' --hard
wp rewrite flush --hard
それでも直らない場合:
- Apache:
.htaccessが無い/書き込めない。またはAllowOverride Noneで読まれていない。 - Nginx:
try_files $uri $uri/ /index.php?$args;が無い。サーバー設定側なので事業者に依頼する。 - 設置場所が変わった(サブディレクトリ ⇄ ドキュメントルート)
→
siteurl/homeのパス部分を実際の設置場所に合わせる。 - 特定の投稿タイプだけ404 → リライトルールの再生成漏れ。プラグイン再有効化で登録し直す。
「管理画面の設定>パーマリンクを開くだけ」でも再生成される。 最も軽い一手。
T5. 管理画面に入れない
まず、どこで止まっているかを分ける。
| 症状 | 原因の方向 |
|---|---|
| ログイン画面が出ない(500 / 白) | T1へ。認証の問題ではない |
| ID/パスが違うと言われる | 認証情報、またはユーザーが消えた |
| ログインは通るが画面が真っ白 | 管理画面側のプラグイン/テーマエラー → T1 |
| ログイン直後にログイン画面へ戻る | Cookie / URL不整合 → T3の1と2を確認 |
| 「権限がありません」 | ロールが壊れている |
wp user list --role=administrator --fields=ID,user_login,user_email
wp user update <ID> --prompt=user_pass # 対話で入力(コマンド履歴に残さない)
パスワードをコマンド引数に書かない。 履歴とプロセス一覧に残る。
- ロールが壊れた場合、ロール定義をリセットするプラグイン/
wp role reset administratorを検討する。 - セキュリティプラグインによるIPロックアウト、2要素認証の失効も多い。 該当プラグインを一時停止して切り分ける(停止したことを記録する)。
- 管理者が身に覚えなく増えていたらT8へ。
T6. 表示が崩れる / 画像が出ない
- 旧ドメインの残存(移行後)
0件でなければ置換漏れ。生SQLで直さない(シリアライズが壊れる)。wp db search 'old.example.com' --all-tables-with-prefix --stats - ファイルが無い —
uploadsの転送漏れ。ファイル数とサイズを両側で照合する。 - 403 — パーミッション/所有者がWeb実行ユーザーと不一致。 ただし画像だけが403なら、WAFが特定の拡張子やパスを弾いている場合もある(T0を参照)。 同じディレクトリの他ファイルが200なら権限ではない。
- サムネイルだけ出ない — 中間サイズ未生成 →
wp media regenerate --yes - CSS/JSが404 — テーマディレクトリ名の大文字小文字違い(macOS/Windows経由で変わる)。
- 混在コンテンツ —
http://の絶対URLが残っている。ブラウザがブロックしている。 - CDN / オフロードプラグインが旧ドメインを指している。
T7. 落ちてはいないが極端に遅い
まず、どこが遅いかを分ける。 全部遅いのか、特定ページだけか、管理画面だけか。
curl -s -o /dev/null -w 'connect:%{time_connect} ttfb:%{time_starttransfer} total:%{time_total}\n' https://example.com
- TTFBが大きい → サーバー/PHP/DB側。
- TTFBは小さいがtotalが大きい → 転送量(画像、JS)。フロント側。
原因候補:
- DBの肥大(
wp_optionsの autoload、期限切れtransient、リビジョン)wp transient delete --expired wp db query "SELECT COUNT(*) FROM $(wp db prefix)options WHERE autoload='yes';" - 外部APIへの同期通信をフックで行うプラグイン。相手が遅いと全ページが遅くなる。
- wp-cron が重い処理を毎リクエストで走らせている
wp cron event list - PHPバージョンが古い、OPcache無効
- 共有サーバーの同居影響、リソース制限
「遅い」は障害と違い、直したつもりで直っていないことが多い。 数値で前後比較する。
T8. 改ざんの疑い
SKILL.md Step 6 が正本。このツリーで対処しようとしない。
判定材料:
wp core verify-checksums
wp plugin verify-checksums --all
wp user list --role=administrator --fields=ID,user_login,user_email,user_registered
find . -type f -name '*.php' -newermt '-7 days' | head -50
- コアのチェックサム不一致は強い兆候(ただし日本語版パッケージ等で差が出ることもあるため、 不一致の内容を確認する)。
- 最近更新していないのに新しいPHPファイルがある場合、その日時が侵入時期の手がかりになる。
保全 → 認証情報の全変更 → 所有者への報告 → クリーンな環境への再構築、の順で計画する。 バックアップからの単純な復元は、バックドアを戻す可能性がある。