EC-CUBE4系でのプラグインエラーの原因と予防対策

*この記事は、 [EC-CUBE4系でプラグインインストール時にエラーが出た時の対処法](https://qiita.com/nanasess/items/583683eb94947aebea44) の詳細版です。
主に、エラーを予防する観点から記述しています。*

EC-CUBE4系では、 フレームワークとして Symfony3.4 が採用され、プラグインの管理に Composer が利用されるようになりました。
モダンな技術を取り入れた反面、動作させるために多くのリソースを消費するようになりました。

----
**2021年11月16日追記**
EC-CUBE4.1.0 がリリースされ Composer v2 が採用されたことにより、 Composer 利用時のメモリ消費が1/10くらいに改善しました。
しかし、プラグインの有効化/無効化時のメモリ消費は改善できておりません。
(Symfony DependencyInjection コンテナのコンパイルに起因するため)
この記事は4.1系でも有用ですので、ご参考になれば幸いです。

----

特に、プラグインのインストール/有効化/無効化/アンインストール時には、以下のような処理が実行されるため、大量のリソースを消費します。

- Composer での依存関係解決
- Composer の classmap 生成
- Symfony DependencyInjection コンテナのコンパイル(キャッシュ生成)
- Doctrine ORM のキャッシュ生成
- Entity Proxy 生成

これらフレームワークのキャッシュを活用することで、運用時のパフォーマンス向上を実現しています。
現代のフレームワークは、キャッシュに支えられているといっても過言ではありません。
*しかし、大量の細かいファイルを生成し読み込むために、 Windows 環境や Docker との相性を悪くしている原因にもなっています。*

プラグインインストール時に発生するトラブルの大半が、これらキャッシュファイルの処理が失敗することによって発生します。
**端的に言うと、キャッシュファイルの運用を安定化させれば、プラグインインストール時のトラブルを無くすことが可能です。**

## 確実にプラグインインストールを成功させるためには

*詳細は後述しますので、手っ取り早く解決したい方は本項のみを読んでください*

プラグインインストール時のトラブルの大半は、フレームワークのキャッシュ生成に失敗することで発生しますので、以下の2点をクリアすれば防止することが可能です。

1. 性能の良いサーバーを使用する
2. メンテナンス画面にして、外部からのリクエストを遮断する

*プラグインの不具合や競合で失敗する場合は、プラグインや本体を修正するしかありません...*

### 性能の良いサーバーを使用する

クラウドや VPS など、潤沢なリソースのサーバーを選択することが重要です。
経験値としては、6コア/メモリ8GB 以上あれば比較的安定しています。
クラウドの場合は、プラグインインストール/有効化/無効化/アンインストール時にスケールアップすると良いと思います。(オートスケールはトラブルの原因になるためおすすめしません)

レンタルサーバーでの利用は、かなり厳しい状況なのですが、、、 **[さくらのレンタルサーバー](https://www.sakura.ne.jp)**は例外です。安価なスタンダードプランでも大丈夫です。
その理由は、 FreeBSD という Linux とは別物の OS を利用しているためです。

*ちなみに FreeBSD を採用している、さくらのレンタルサーバーも半強制的なPHPのバージョンアップがあったり、パーミッション設定の関係から[少々セキュリティに課題](https://qiita.com/nanasess/items/19ef094309f50009c742#web%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%81%AE%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E6%A8%A9%E9%99%90%E3%81%A7%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%95%E3%81%9B%E3%81%AA%E3%81%84%E3%81%9F%E3%82%81%E3%81%AB)が残っていたりします。。。*

**(2025-04-11 追記) 最近のさくらのレンタルサーバーは、リソース制限が厳しくなったようで、処理のタイミングによっては Linux サーバー同様にプロセスが強制終了してしまう場合があります。**

プラグインをインストールする際、大量のリソースを消費します。
性能の低い Linux サーバーですと、サーバーダウンの危険があるため [OOM Killer という OS 保護機構が働いて、プラグインインストールのプロセスを強制終了](https://github.com/EC-CUBE/ec-cube/issues/4142)させてしまいます。
これがプラグインインストールトラブルの多くの原因になっているのですが、 FreeBSD には、この OOM Killer がありません。
OOM Killer によって、プラグインインストールのプロセスが強制終了されることは無いために、安価なスタンダードプランでも安定してインストールできます。

性能の高いサーバーや、 FreeBSD でもシステムエラーになるケースがあるのですが、次項のメンテナンス画面を併用することで、ほぼ解消できると思います。

### メンテナンス画面にして、外部からのリクエストを遮断する

無事にプラグインのインストールが成功しても、有効化時にシステムエラーになる場合があります。
プラグインの有効化をする際、各種キャッシュファイルを生成し直すのですが、このときに外部からのアクセスがあると、複数のプロセスでキャッシュファイル生成が競合してしまう場合があり、システムエラーの原因になります。
これは、メンテナンス画面にして、外部からのリクエストを遮断することで解消できます。

EC-CUBE4.0.1以降では、  EC-CUBE をインストールしたフォルダ直下に `.maintenance` というファイル名のファイル(中身は何でも良い)を置くと、メンテナンス画面になります。

具体的な手順は、以下の通りです。

1. `<EC-CUBEインストールフォルダ>/.maintenance` ファイルを設置する
2. フロント画面がメンテナンス画面になったのを確認する
3. プラグインインストール/有効化/無効化/アンインストールを実行する([コマンドラインから実行すると、より安定します。 ](https://qiita.com/nanasess/items/791c9ec98f69ada93ea0#コマンドラインでのプラグインインストール))
4. 管理画面を何度かリロードして、システムエラーにならないのを確認する
5. `<EC-CUBEインストールフォルダ>/.maintenance` ファイルを削除する
6. フロント画面が正常に表示されるのを確認する

4 でシステムエラーになった場合は、プラグインの不具合や、競合の可能性があります。
プラグインや本体を修正する必要がありますので、 `var/log` 以下にあるログの**システムエラー**と表示されている行をご確認ください。

#### コマンドラインでのプラグインインストール

管理画面からのWebインストーラよりも、コマンドライン操作の方が格段に安定しています。
何度やってもWebインストールに失敗してしまう場合、コマンドライン操作に慣れている方はお試しください。

オーナーズストアプラグイン、独自プラグインでコマンドが異なりますのでご注意ください。
事前にメンテナンス画面に変更しておくことを忘れずに。
キャッシュ削除/キャッシュ生成もコマンドラインで実行するのがポイントです。

```shell
## 事前準備 - メンテナンス画面に変更
touch .maintenance

## オーナーズストアプラグインインストール
bin/console eccube:composer:require ec-cube/<PluginCode>
bin/console eccube:plugin:install --code <PluginCode>

bin/console cache:clear --no-warmup # キャッシュ削除
bin/console cache:warmup # キャッシュ生成

## 独自プラグインインストール
bin/console eccube:plugin:install --code <PluginCode>
bin/console cache:clear --no-warmup # キャッシュ削除
bin/console cache:warmup # キャッシュ生成

## プラグイン有効化
bin/console eccube:plugin:enable --code <PluginCode>
bin/console cache:clear --no-warmup # キャッシュ削除
bin/console cache:warmup # キャッシュ生成

## プラグイン無効化
bin/console eccube:plugin:disable --code <PluginCode>
bin/console cache:clear --no-warmup # キャッシュ削除
bin/console cache:warmup # キャッシュ生成

## オーナーズストアプラグインアンインストール
bin/console eccube:composer:remove ec-cube/<PluginCode>
bin/console cache:clear --no-warmup # キャッシュ削除
bin/console cache:warmup # キャッシュ生成

## 独自プラグインアンインストール
bin/console eccube:plugin:uninstall --code <PluginCode>
bin/console cache:clear --no-warmup # キャッシュ削除
bin/console cache:warmup # キャッシュ生成

## オーナーズストアプラグインアップデート
bin/console eccube:composer:require ec-cube/<PluginCode>
bin/console eccube:plugin:update <PluginCode>
bin/console cache:clear --no-warmup # キャッシュ削除
bin/console cache:warmup # キャッシュ生成

## 独自プラグインアップデート
bin/console eccube:plugin:update <PluginCode>
bin/console cache:clear --no-warmup # キャッシュ削除
bin/console cache:warmup # キャッシュ生成

## メンテナンス画面を解除
rm .maintenance
```

## プラグインエラーの原因と対処法詳細

### Composer での依存関係解決時のエラー

EC-CUBE4系では、 Composer を利用して、プラグインの依存関係を制御しています。
EC-CUBE に限らず Laravel で開発したプロジェクトなど、 Composer を使用するプロジェクトすべてにあてはまるのですが、 `composer require` コマンドを実行する際に400MB〜600MBのメモリを消費します。
これは、Composer の依存関係にある JSON ファイルをすべてメモリ上に読み込むためです。

通常、 Composer の操作はコマンドラインで実行するため、問題になることは少ないのですが、 EC-CUBEの場合は Webインターフェイスを使用するために問題になります。

1リクエストで**400MB〜600MBのメモリを消費するWebアプリケーション**というのは明らかに異常な状態です。
(通常は多くても数十MB)
CPUの利用率も高い状況が継続するため、Linux では [OOM Killer という OS 保護機構が働いて、プラグインインストールのプロセスを強制終了](https://github.com/EC-CUBE/ec-cube/issues/4142)させてしまいます。

このケースでは、エラーログが出力されない場合があり、原因の特定を困難にさせる一因となっています。

#### 対処方法

OOM Killer は Linux 固有の機構ですので、[さくらのレンタルサーバー](https://www.sakura.ne.jp/)で採用されている FreeBSD など、 Linux 以外の OS では影響を受けません。
また、クラウドや VPS などで性能の良いインスタンスを使用することで、 OOM Killer の影響を低減させることが可能です。

管理画面から実行するよりも、[コマンドラインから実行](https://qiita.com/nanasess/items/791c9ec98f69ada93ea0#コマンドラインでのプラグインインストール)した方がより安定します。

よく、 php.ini の `memory_limit` を増やしましょうという対処法を紹介しているブログなどがあるのですが、このケースの場合は殆ど意味がありません。
Composer は、内部的に `memory_limit` を 1.5GB まで自動的に増加させるためです。
(つまり、メモリ 1.5GB 未満のミニマムな環境では危険な状態になります)

Docker を使用する場合は [--oom-kill-disable](http://docs.docker.jp/engine/reference/run.html?highlight=docker%20run#runtime-constraints-on-resources) というオプションがありますので、試してみると良いでしょう。

まとめると、以下の2点の対応で解消できる可能性が高いです。

- 性能の良い環境を使用する or Linux 以外の OS を使用する
- コマンドラインから実行する

### Composer の classmap 生成時のエラー

プラグインをインストールする場合、 Composer API を使用して、プラグインのPHPプログラムがオートローディング用の classmap に追加されます。
フレームワークのキャッシュファイルや、プラグインが自動生成したファイルも、 classmap に追加されるのですが、生成タイミングによっては、追加されずに漏れてしまい、不整合が発生する場合があります。
特に、 [Entity 拡張](https://doc4.ec-cube.net/customize_entity)に失敗して、この問題が発生する場合が多いです。

この場合、システムエラーになってしまい、画面を何度もリロードしても復旧しなくなってしまいます(途方に暮れる場合が多い)

キャッシュファイルの不整合の場合は、キャッシュクリアしたり、画面を何度かリロードすれば復旧する場合が多いのですが、 Composer の classmap の場合は自動的に再生成されないため、コマンドラインから生成し直す必要があります。

#### 対処方法

`composer dumpautoload` コマンドで classmap を生成し直します。
事前に、[Composer コマンド](https://getcomposer.org/download/) のインストールが必要です。

```shell
## 事前準備 - メンテナンス画面に変更
touch .maintenance

php composer.phar dumpautoload # classmap を生成し直す
bin/console cache:clear --no-warmup # キャッシュ削除
bin/console cache:warmup # キャッシュ生成

## メンテナンス画面を解除
rm .maintenance
```

### Symfony DependencyInjection コンテナのコンパイル時のエラー

EC-CUBE4系では、 DIコンテナとして Symfony DependencyInjection Component を採用しています。
この DI コンテナは、リクエストを検知するとDIコンポーネントのキャッシュファイルを自動的に生成(コンパイル)してからレスポンスを返します。
キャッシュを削除した直後に、複数のリクエストを同時に受信すると、リクエストごとにキャッシュファイルの生成処理が起動してしまい、結果的にキャッシュの不整合が発生してシステムエラーの原因になります。

このエラーは、 **システムエラーが発生しました。** というログに以下のような **Container<ランダム文字列>** が含まれているのが特徴です。

```/path/to/ec-cube/var/log/prod/site-log-YYYY-MM-DD.log
[2020-05-18 14:30:45] front.ERROR [N/A] [d8c46ea] [N/A] [Eccube\Log\Logger:log:66] - システムエラーが発生しました。
... snip
#10 /path/to/ec-cube/var/cache/prod/ContainerZkkhqxc/EccubeProdProjectContainer.php(3190): ContainerZkkhqxc\\EccubeProdProjectContainer->getTwigInitializeListenerService()`
...
```

やっかいなことに、このエラーは大量のコアを詰んだ高性能なサーバーや、 OOM Killer 
の発生しない FreeBSD でも発生します。

また、 memory_limit が PHP 標準の 128MB くらいになっていたりすると、だいたいこの処理で **Fatal error: Allowed memory size of xxx bytes exhausted (tried to allocate xxx bytes) in /xxx/xxx.php on line xxx.** というエラーになります。

#### 対処方法

このエラーの場合は、管理画面からキャッシュ削除したり、ブラウザを何度かリロードすると、キャッシュが再生成されて復旧される場合があります。

予防するためには、事前にメンテナンス画面に切り替えて、外部からのアクセスを遮断することが有効です。

コマンドラインから実行する場合は、 `bin/console cache:warmup` コマンドを使用して、キャッシュ生成してからメンテナンス画面を解除するようにしましょう。

```shell
## 事前準備 - メンテナンス画面に変更
touch .maintenance

bin/console cache:clear --no-warmup # キャッシュ削除
bin/console cache:warmup # キャッシュ生成

## メンテナンス画面を解除
rm .maintenance
```

### Doctrine ORM のキャッシュ生成時のエラー

Doctrine ORM は、 Symfony が採用している O/R Mapping フレームワークです。
EC-CUBE でも、データベースアクセス時に利用しています。

この Doctrine ORM は、遅延読み込み機能(Lazy-Loading)を実現するために、 自動的にキャッシュファイル(Proxy クラス)を生成します。
*(後述する `app/proxy` 以下のファイルとは別物です)*

通常は、キャッシュファイルを生成してからレスポンスを返すのですが、複数のプロセスでキャッシュファイル生成が競合してしまうと、キャッシュ生成前にレスポンスを返してしまい、システムエラーとなってしまいます。

このエラーは、 **システムエラーが発生しました。** というログに以下のような `__CG__` から始まる PHP ファイルが含まれているのが特徴です。

```/path/to/ec-cube/var/log/prod/site-log-YYYY-MM-DD.log
[2020-05-14 17:37:57] admin.ERROR [a3b9d5e0] [214492c] [N/A] [Eccube\Log\Logger:log:64] - システムエラーが発生しました。 ["Compile Error: require(): Failed opening required '/path/to/ec-cube/var/cache/prod/doctrine/orm/Proxies/__CG__EccubeEntityMasterWork.php' (include_pa
th='.:/usr/local/php/7.3/lib/php')","/path/to/ec-cube/vendor/doctrine/common/lib/Doc
trine/Common/Proxy/Autoloader.php",74,"#0 {main}"] [GET, /ec-cube/admin/store/plugin, 147.192.
```

#### 参考(英語記事です)

- https://www.doctrine-project.org/projects/doctrine-orm/en/2.7/reference/advanced-configuration.html
- https://www.uvdesk.com/en/blog/doctrine-proxy-objects-lazy-loading/

#### 対処方法

このエラーはの多くは一時的なもので、再度画面をリロードすることで復旧する場合がほとんどです。
やはり予防するためには、事前にメンテナンス画面に切り替えて、外部からのアクセスを遮断することが有効です。

コマンドラインから実行する場合は、 `bin/console cache:warmup` コマンドを使用して、キャッシュ生成してからメンテナンス画面を解除するようにしましょう。

```shell
## 事前準備 - メンテナンス画面に変更
touch .maintenance

bin/console cache:clear --no-warmup # キャッシュ削除
bin/console cache:warmup # キャッシュ生成

## メンテナンス画面を解除
rm .maintenance
```

### Entity Proxy 生成時のエラー

EC-CUBE4系では、[Entity 拡張](https://doc4.ec-cube.net/customize_entity)という機能を利用して、プラグインでエンティティの属性を追加することが可能です。
この機能を利用する際、 **Entity Proxy** という PHP ファイルを `app/proxy` 以下に生成します。
*(前述の Doctrine ORM の Proxy とは別物です)*

プラグイン有効化/無効化時に、このファイルを生成するのですが、 `app/proxy/entity/`　以下の読み込みと `src/Eccube/Entity/` の読み込みが同時に発生するタイミングがあり、 通常の運用時にも `PHP Fatal error: Cannot declare class` というエラーが内部で発生します。(参考 [EC-CUBE/ec-cube#4173](https://github.com/EC-CUBE/ec-cube/issues/4173#issuecomment-496923069))

```/path/to/ec-cube/var/log/prod/site-log-YYYY-MM-DD.log
[php7:error] [pid 22690] [client 203.x.x.x:52619] PHP Fatal error: Cannot declare class Eccube\Entity\ProductClass, because the name is already in use in /path/to/ec-cube/app/proxy/entity/ProductClass.php on line 28, referer: https://example.com/store/plugin/api/upgrade/1/confirm
```

通常は、システムエラー画面にならないよう制御されており、エラーメッセージがログに残るだけなのですが、プラグインの不具合であったり、キャッシュファイルの不整合が引き金となって、システムエラー画面になってしまう場合があります。

以下のように、エラーログに `app/entity/proxy` が含まれており、かつ `PHP Fatal error: Cannot declare class` ではないエラーメッセージの場合は、システムエラー画面になってしまい、キャッシュクリアしても復旧しない場合があります。

```/path/to/ec-cube/var/log/prod/site-log-YYYY-MM-DD.log
システムエラーが発生しました。 ["Compile Error: require(): Failed opening required '/path/to/ec-cube/app/entity/proxy...
```

場合によっては、システムエラーの影響で、管理画面に入れなくなったり、メンテナンス画面への切替もできないケースもあります。

#### 対処方法

この場合は、 Entity proxy クラスを再生成した後に Composer classmap を再生成する必要があります。

```shell

## 事前準備 - メンテナンス画面に変更
#(メンテナンス画面に切り替わらなくてもファイルは生成しておく)
touch .maintenance

# bin/console コマンドが動作しない場合もあるので、 composer install を実行して不整合を解消する
php composer.phar install

bin/console eccube:generate:proxies # Entity proxy を再生成
php composer.phar dumpautoload # classmap を生成し直す
bin/console cache:clear --no-warmup # キャッシュ削除
bin/console cache:warmup # キャッシュ生成

## メンテナンス画面を解除
rm .maintenance
```

### CGIモードでのサーバーエラー

さくらのレンタルサーバーなど、一部のレンタルサーバーでは、 PHPの実行モードを選択できます。
CGIモードと、モジュールモードがあり、通常はモジュールモードで動作します。
しかし古い契約プランでは、CGIモードしか選択できない場合があります。
*(php-fpm を使用する FastCGI とは異なります)*

CGIモードの PHP では EC-CUBEは動作保証されておらず、プラグイン有効化時などにサーバーエラーが発生します。
EC-CUBEのエラー画面では無いエラー画面が表示されるのが特徴です。

また、このエラーが発生した場合は、 `var/log` 以下にあるEC-CUBEのログにエラーは記録されません。

サーバーのエラーログに、以下のような内容が記録される場合があります。

```/var/log/httpd/error.log
[Thu Jun 11 15:57:46.492977 2020] [cgi:error] [pid 10793] [client 217.178.90.58:0] malformed header from script 'index.php': Bad header: gen -> /tmp//proxy_aceBBaJq9tJ, referer: https://example.com/path/to/ec-cube/admin/store/plugin
```

#### 対処方法

PHPをモジュールモードに変更します。([さくらのレンタルサーバーでの変更方法はこちら](https://help.sakura.ad.jp/115000135681/))
CGIモード以外に選択できない場合は、サーバー移転をご検討ください。

#### 参考

- [さくらのレンタルサーバー - PHPのバージョン変更](https://help.sakura.ad.jp/115000135681/)


### max_execution_time タイムアウト

**[max_execution_time](https://www.php.net/manual/ja/info.configuration.php#ini.max-execution-time)** はプログラムの暴走を止めるためのタイムアウトです。
デフォルトでは30秒に設定されています。
プラグインインストールは、30秒以上の時間がかかる場合が多く、インストールや有効化に失敗した場合は、この設定を疑われる方が多いです。
[公式のよくある質問](https://support.ec-cube.net/hc/ja/articles/360038928051-4系で-EC-CUBE管理画面の-プラグインを探す-からインストール後-エラーが発生します-)にも、 **max_execution_timeが30→max_execution_timeを180に設定** と書かれています。

実は、この設定が問題になる場合は少ないです。
この設定を変更される方が多いですが、ほとんどの場合意味無いです。

PHP公式ドキュメントには、**最大実行時間は、システムコール、ストリーム操作等の影響を受けません** とあります。
プラグインインストールや有効化の処理は、ストリーム操作などが大半なのが理由です。

エラーログに、以下のようなエラーメッセージを見つけた場合のみ、この設定を変更するようにしましょう。

```
Fatal error: Maximum execution time of 30 seconds exceeded
```

また、このエラーが発生した場合は、 `var/log` 以下にあるEC-CUBEのログにエラーは記録されず、 Webサーバーのエラーログ(`/var/log/httpd/error_log` 等)に記録される場合もあるため、ご注意ください。

### FastCGI のタイムアウト

Ngnix や Apache event MPM などの Webサーバーでは FastCGI という実行モードが使用されます。
(前出の[CGIモード](#cgiモードでのサーバーエラー)とは別物です)
php-fpm という実装が利用されるのですが、いくつかタイムアウトの設定があります。

プラグインインストール/有効化/無効化/アンインストール時に、これらのタイムアウトに抵触した場合、エラー画面にならずに長い間応答が返ってこない場合が多いです。
php-fpm を使用していて、長い間応答が返ってこない場合はこれらのエラーである疑いが強いです。

php-fpm には [request_terminate_timeout](https://www.php.net/manual/ja/install.fpm.configuration.php) という設定項目があります。
この項目は、前出の [max_execution_time](#max_execution_timeタイムアウト)オプションが何らかの理由でスクリプトの実行を止められなかった場合に利用されます。
デフォルト値は 0 (OFF)です。

```/etc/php-fpm.d/php-fpm.conf
request_terminate_timeout = 0
```

Nginx には `fastcgi_read_timeout` という設定項目があります。php-fpm がこの時間内に何も送信しない場合は接続が切断されます。
デフォルト値は60秒です。

```/etc/nginx/nginx.conf
fastcgi_read_timeout 60
```

これらエラーが発生した場合は、 `var/log` 以下にあるEC-CUBEのログにエラーは記録されず、 Webサーバーのエラーログ(`/var/log/nginx/error.log` 等)や PHPのエラーログ(`/var/log/php_error.log` 等)に記録されます。

#### 参考

- [504 Gateway Time-out が出た際は Elastic Load Balancing の設定にも注意しよう](https://qiita.com/kotarella1110/items/169ddcef03983f5d64b2)

### インストール中のDBエラーによるロールバック

- プラグイン一覧に、プラグインが表示されない
- `app/Plugin/<Pluginコード>` にはプラグインファイルが存在しているのに
- dtb_plugin テーブルには該当のプラグインが存在しない

上記のような状況になってしまった場合は、インストール中に何らかのエラーが発生し、プラグインのインストール処理の途中でデータベースのみがロールバックしてしまった可能性があります。

この原因は様々ですが、プラグイン自体の不具合や、プラグイン同士の競合である可能性が高いです。
また、プラグイン自体は **インストール完了しました** と表示される場合もあり、原因の特定を困難にしているケースもあります。

#### 対処方法

原因となっているプラグインを特定する必要がありますので、プラグインを1つずつアンインストールして確認するのが良いでしょう。

プラグイン一覧に、プラグインが表示されない場合は、コマンドラインからアンインストールを試みると良いと思います。

```shell
## オーナーズストアプラグインアンインストール
bin/console eccube:composer:remove ec-cube/<PluginCode>
bin/console cache:clear --no-warmup # キャッシュ削除
bin/console cache:warmup # キャッシュ生成

## 独自プラグインアンインストール
bin/console eccube:plugin:uninstall --code <PluginCode>
bin/console cache:clear --no-warmup # キャッシュ削除
bin/console cache:warmup # キャッシュ生成
```

根本的には、エラーの発生原因(プラグイン自体の不具合, 競合など)を特定し、解消する必要があります。

### composer.json の不整合

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">もしかしたら、プラグインのインストールは成功したけど、 composer の依存関係を解決する際に、リソース不足などで composer.json 自体が巻き戻ってしまったのかもしれません</p>&mdash; 🍣大河内健太郎🕊💉 (@nanasess) <a href="https://twitter.com/nanasess/status/1261607225405014016?ref_src=twsrc%5Etfw">May 16, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

EC-CUBE4系では、プラグインの依存関係の解決に composer を使用しています。
プラグインのインストール では composer API によって `composer require` コマンドが内部的に実行され、Symfony によってキャッシュが生成されます。

composer パッケージの依存関係を解決できなかったり、リソース不足などでキャッシュがうまく生成できなかったりすると、 **プラグインのインストールは完了しているのに、 composer.json は巻き戻っている** もしくは **composer.json には登録されているのに、プラグインのインストールは完了していない** 状態になる場合があります。

このような状態になってしまうと、Symfony によるキャッシュ生成もできません。
リロードを繰替えしたりキャッシュを削除しても、システムエラーから復旧しない場合は、 この composer.json の不整合の疑いが強いです。

`bin/console cache:clear --no-warmup` コマンドや、 `composer install` コマンドを実行した場合、以下のような **アンインストールを促すメッセージ** が出る場合があります。

```
 [RuntimeException]
  You can not uninstall the EC-CUBE plugin via `composer` command.
  Please use the `bin/console eccube:composer:remove ec-cube/<Plugin code>` instead.
```

この場合、エラーメッセージとは逆に、 `bin/console eccube:composer:require ec-cube/<Plugin code>` で該当のプラグインを一旦インストールすると復旧するケースが多いです。

#### 対処方法

何が原因で依存関係が壊れているか様々ですので、一旦手動でプラグインをすべて削除してみるのが良いでしょう。

1. データベースとソースコードのバックアップを取得
2. dtb_plugin のデータをすべて削除
3. app/Plugin のデータをすべて削除
4. composer.json 及び composer.lock をデフォルト状態に戻す
5. `composer install` コマンドを実行

これで復旧すれば、再度1つずつプラグインを再インストールしてみましょう

### ブラウザのタイムアウト、レンサバのプロセス実行タイムアウト

プラグインインストールや、削除時のプログレスバーが出たまま、処理が終了しない場合は、ブラウザのタイムアウトや、レンタルサーバーのプロセス実行タイムアウトが考えられます。

**処理が終わらないが、エラーログも出ていない** ケースが多いため、原因を特定するのが難しいです。

#### 対処方法

一般的に10分以上処理が終わらない場合、サーバー側では既に処理が異常終了しているケースが多いです。
一旦、ブラウザを閉じて、再度プラグイン管理画面にアクセスし、該当のプラグインの処理が完了しているかどうか再確認してください。

インストールや削除が完了していない場合は、キャッシュクリア後に再度試してみましょう。

### プラグインの不具合、競合

プラグインインストール/有効化/無効化/アンインストールの操作を何度繰替えしても、システムエラーが改善しない場合は、**プラグイン自体の不具合や競合** である場合が多いです。
特に、プラグインインストール/有効化/無効化/アンインストールのプログラムに不具合があると、管理画面自体がシステムエラーになってしまい、何もできなくなる場合があります。

#### 対処方法

どのプラグインで不具合が発生しているか、特定することが重要です。
問題を切り分けるために一旦手動でプラグインをすべて削除してみるのが良いでしょう。

1. データベースとソースコードのバックアップを取得
2. dtb_plugin のデータをすべて削除
3. app/Plugin のデータをすべて削除
4. composer.json 及び composer.lock をデフォルト状態に戻す
5. `composer install` コマンドを実行

これで復旧すれば、再度1つずつプラグインを再インストールしてみましょう

### プラグインインストール/アンインストール中のDBエラーによるロールバック

プラグインをアンインストールしたが、**プラグイン一覧に該当のプラグインが表示されたまま**
であったり、**インストール完了しました**と表示されたが、プラグイン一覧には表示されていない場合は、データベースエラーでロールバックしてしまった可能性が考えられます。
このケースも、ログにエラーが記録されない場合がありますので、以下の点を確認してみると良いでしょう。

- `app/Plugin` 以下に該当のプラグインが存在するか
- dtb_plugin に該当のプラグインのレコードが存在するか

プラグインインストール時に問題が発生した場合は、

**`app/Plugin` 以下に該当のプラグインが存在するが、dtb_plugin に該当のプラグインのレコードが存在しない**

プラグインアンインストール時に問題が発生した場合は、

**`app/Plugin` 以下に該当のプラグインは存在しないが、dtb_plugin に該当のプラグインのレコードが存在する**

といった不整合が発生している場合が多いです。

#### 対処方法

##### プラグインインストール時に問題が発生した場合

手動で dtb_plugin に該当のレコードを登録し、キャッシュクリアしてみましょう。
以下の SQL を参考にしてください。

```sql
INSERT INTO dtb_plugin
(name, code, enabled, version, source, initialized, create_date, update_date, discriminator_type)
VALUES('<プラグイン名>', '<プラグインコード>', 0, '<プラグインバージョン>', '', 1, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'plugin');

```

##### プラグインアンインストール時に問題が発生した場合

手動で dtb_plugin の該当レコードを削除し、キャッシュクリアしてみましょう。
削除のSQLは以下を参考にしてください。

```sql
DELETE FROM dtb_plugin WHERE code = '<プラグインコード>';
```

### リソース(メモリ、CPU)不足

何もエラーなど出ないのに、

- サイトが応答しない
- FTP アクセスできない
- DBアクセスできない

といった不具合が発生する場合があります。この場合は、メモリやCPUなどのリソース不足である場合が多いです。
メモリ2GB未満の環境ですと、このようなエラーになりやすいです。

#### 対処方法

サーバーを再起動してみるのが良さそうです。
再起動もできない場合は、強制リブートや強制シャットダウンするしかないかもしれません。
頻発するようなら、性能の高いサーバーへの移行をおすすめいたします。

## どうしても解決できないときは

この投稿のコメント覧でお問い合わせください