事象
実行権限が必要なファイルを git 管理して rsync で配信すると、デプロイ中に一時的にサイトが 500 になる。
2026-07-28 に branddesigncontest.com のデプロイ中、本番が Internal Server Error になった(デプロイ完了後は自動的に復旧)。
原因
さくらインターネットで PHP バージョンを個別指定しているサイトは、.htaccess と php.cgi を使う。
Action myphp-script /php.cgi
AddHandler myphp-script .php
この php.cgi は実行権限が必要(705 や 711)。しかし:
- git は実行ビットしか記録できない(
100644 か 100755 のみ)。該当サイトでは 100644(実行不可)で記録されていた
- rsync は
--perms 付きで動作するため、転送直後に本番の php.cgi が 644 = 実行不可になる
- → PHP ハンドラが動かず、サイト全体が 500
after_sync の chmod が走って初めて復旧する
つまり rsync 完了 〜 after_sync 完了の数十秒間、サイトが落ちる。
メンテナンス画面では防げない
.maintenance による WordPress のメンテナンス画面は、PHP が動作して初めて表示される。php.cgi が実行できない状態では PHP 自体が起動しないため、メンテ画面も出せずに 500 が露出する。
.depinc-extra.sh のフックでも防げない
#9 で追加したフック(after_sync_extra)は名前の通り rsync の後にしか実行できない。パーミッションを正すのが「壊れた後」になるため、500 の窓は塞げない。
対策
git に記録するモードを 100755 にする。ファイル自体に実行権限を付けること。
chmod +x php.cgi
git add php.cgi
git commit -m "..."
コミット時に mode change 100644 => 100755 php.cgi と表示されれば成功。
これで rsync 直後から実行可能になり、500 の窓が消える。その後 after_sync_extra が 711 / 705 に絞る流れは変わらない。
一時的に 755(other が読み取り可)になるが、php.cgi の中身は PHP バージョン指定の数十バイトのみで、時間も数秒。500 を出し続けるより安全と判断した。
⚠️ git update-index --chmod=+x は使わないこと。 core.fileMode = true の環境では git がファイル実体の実行ビットを見るため、インデックスだけ書き換えても後続の git 操作で元に戻る。実際、これで2回失敗した(1回目はコミット漏れ、2回目はインデックスがリセットされていた)。
検証結果(2026-07-28)— 対策は有効
対応の前後で、デプロイ中のサイトの挙動が明確に変わった。
|
対応前 |
対応後 |
| デプロイ中の表示 |
500 Internal Server Error |
WordPress のメンテナンス画面 |
php.cgi の git モード |
100644 |
100755 |
branddesigncontest.com / niwa-archives.org の両方で確認済み。
デプロイログでも、フックが意図通り動いていることを確認した。
[DEPLOY] - WP core version -> OK (server: 7.0.2 / repo: 7.0.2)
[DEPLOY] - php.cgi -> chmod 711 # niwa は 705
この結果は2つのことを同時に裏付けている。
- 対策が有効である — rsync 直後から
php.cgi が実行可能になり、500 の窓が消えた
- 「PHP が動かないとメンテナンス画面も出せない」という因果関係 — 対応前にメンテ画面が出なかったのは
.maintenance が作られなかったからではなく、PHP 自体が起動できなかったため。対策後は同じ .maintenance が正しく機能している
対象サイト
php.cgi を使っている(=さくらで PHP バージョンを個別指定している)サイト。
他にも同じ構成のサイトがあれば同じ罠を踏む。確認方法:
git ls-files -s php.cgi # 100644 なら要対応
根本的な検討課題
「実行権限が必要なファイルを git 管理して rsync する」構成自体に無理がある。git が 644/755 の2値しか持てない以上、711 や 705 のような細かいパーミッションはデプロイ後に付け直すしかない。
代替案:
php.cgi を git 管理から外す(.gitignore + .depignore)。サーバ側にだけ置き、デプロイで触らない。環境ごとに PHP バージョンが違うので、そもそも git 管理する必然性が薄い
- rsync に
--chmod を渡してファイル種別ごとにパーミッションを指定する
.htaccess を最後に転送する(順序制御が必要で複雑)
1つ目が最も素直だと思われる。php.cgi はサーバ固有の設定ファイルであり、コードではない。
関連
事象
実行権限が必要なファイルを git 管理して rsync で配信すると、デプロイ中に一時的にサイトが 500 になる。
2026-07-28 に branddesigncontest.com のデプロイ中、本番が Internal Server Error になった(デプロイ完了後は自動的に復旧)。
原因
さくらインターネットで PHP バージョンを個別指定しているサイトは、
.htaccessとphp.cgiを使う。この
php.cgiは実行権限が必要(705 や 711)。しかし:100644か100755のみ)。該当サイトでは100644(実行不可)で記録されていた--perms付きで動作するため、転送直後に本番のphp.cgiが 644 = 実行不可になるafter_syncのchmodが走って初めて復旧するつまり rsync 完了 〜 after_sync 完了の数十秒間、サイトが落ちる。
メンテナンス画面では防げない
.maintenanceによる WordPress のメンテナンス画面は、PHP が動作して初めて表示される。php.cgiが実行できない状態では PHP 自体が起動しないため、メンテ画面も出せずに 500 が露出する。.depinc-extra.shのフックでも防げない#9 で追加したフック(
after_sync_extra)は名前の通り rsync の後にしか実行できない。パーミッションを正すのが「壊れた後」になるため、500 の窓は塞げない。対策
git に記録するモードを
100755にする。ファイル自体に実行権限を付けること。chmod +x php.cgi git add php.cgi git commit -m "..."コミット時に
mode change 100644 => 100755 php.cgiと表示されれば成功。これで rsync 直後から実行可能になり、500 の窓が消える。その後
after_sync_extraが 711 / 705 に絞る流れは変わらない。一時的に 755(other が読み取り可)になるが、
php.cgiの中身は PHP バージョン指定の数十バイトのみで、時間も数秒。500 を出し続けるより安全と判断した。検証結果(2026-07-28)— 対策は有効
対応の前後で、デプロイ中のサイトの挙動が明確に変わった。
php.cgiの git モード100644100755branddesigncontest.com / niwa-archives.org の両方で確認済み。
デプロイログでも、フックが意図通り動いていることを確認した。
この結果は2つのことを同時に裏付けている。
php.cgiが実行可能になり、500 の窓が消えた.maintenanceが作られなかったからではなく、PHP 自体が起動できなかったため。対策後は同じ.maintenanceが正しく機能している対象サイト
php.cgiを使っている(=さくらで PHP バージョンを個別指定している)サイト。他にも同じ構成のサイトがあれば同じ罠を踏む。確認方法:
git ls-files -s php.cgi # 100644 なら要対応根本的な検討課題
「実行権限が必要なファイルを git 管理して rsync する」構成自体に無理がある。git が 644/755 の2値しか持てない以上、711 や 705 のような細かいパーミッションはデプロイ後に付け直すしかない。
代替案:
php.cgiを git 管理から外す(.gitignore+.depignore)。サーバ側にだけ置き、デプロイで触らない。環境ごとに PHP バージョンが違うので、そもそも git 管理する必然性が薄い--chmodを渡してファイル種別ごとにパーミッションを指定する.htaccessを最後に転送する(順序制御が必要で複雑)1つ目が最も素直だと思われる。
php.cgiはサーバ固有の設定ファイルであり、コードではない。関連