Mauticアップデートで`Doctrine\ORM\Mapping\MappingException`が出た時の対応

Mautic(特に古いバージョンのもの)を最新版にアップデートする際、まれにsite is offlineになるケースがあります。

その場合は落ち着いて以下の2つを実施しましょう。

  • サーバーのエラーログを確認する
  • SSHして、symfonyコマンドを実行する

サーバーのエラーログを確認する

今回こちらで発生したケースでは、/var/log/httpd/ssl_error.logに以下のエラーが出ていました。

[Sun Jan 07 02:14:31.417360 2018] [:error] [pid 9078] [client 111.232.123.80:57156] PHP Warning:  require(/var/www/html/app/cache/prod/doctrine/orm/Proxies/__CG__MauticPluginBundleEntityPlugin.php): failed to open stream: No such file or directory in /var/www/html/vendor/doctrine/common/lib/Doctrine/Common/Proxy/AbstractProxyFactory.php on line 209, referer: https://ec2-13-230-186-49.ap-northeast-1.compute.amazonaws.com/s/login
[Sun Jan 07 02:14:31.417396 2018] [:error] [pid 9078] [client 111.232.123.80:57156] PHP Fatal error:  require(): Failed opening required '/var/www/html/app/cache/prod/doctrine/orm/Proxies/__CG__MauticPluginBundleEntityPlugin.php' (include_path='.:/usr/share/pear:/usr/share/php') in /var/www/html/vendor/doctrine/common/lib/Doctrine/Common/Proxy/AbstractProxyFactory.php on line 209, referer: https://ec2-13-230-186-49.ap-northeast-1.compute.amazonaws.com/s/login

SSHして、symfonyコマンドを実行する

php app/console cache:warmup --env=prodでMauticが持っているキャッシュを削除することができます。

このコマンドを実行して、復旧しないか確認してみましょう。

これを実行後にサイトが復旧すれば、キャッシュによるものと思われます。
が、今回遭遇したケースでは以下のようにエラーが発生しました。

$ php app/console cache:warmup --env=prod

 // Warming up the cache for the prod environment with debug false                                                      



  [Doctrine\ORM\Mapping\MappingException]                                                                                         
  Duplicate definition of column 'id' on entity 'Mautic\CoreBundle\Entity\MessageQueue' in a field or discriminator column mapping.                                                                                                                             


cache:warmup [--no-optional-warmers] [-h|--help] [-q|--quiet] [-v|vv|vvv|--verbose] [-V|--version] [--ansi] [--no-ansi] [-n|--no-interaction] [-s|--shell] [--process-isolation] [-e|--env ENV] [--no-debug] [--] <command>

Duplicate definition of column 'id' on entity 'Mautic\CoreBundle\Entity\MessageQueue' in a field or discriminator column mapping.の対応

以下のようにすることで、サイトを復旧できました。

# rm app/bundles/CoreBundle/Entity/MessageQueue.php
# rm -rf app/cache/prod/ or sudo -u apache php app/console cache:warmup --env=prod

app/bundles/CoreBundle/Entity/MessageQueue.phpを削除することに抵抗がある場合、mv app/bundles/CoreBundle/Entity/MessageQueue.php /tmpなどで関係のない場所に移動させればOKです。

参考

https://github.com/mautic/mautic/issues/1508
https://github.com/mautic/mautic/issues/5459

CLIでMauticコアのアップデートが"Package could not be found!"となった場合の対応

Issueも立てているのですが、手動での対応法を覚書として残しておきます。

現象

2.9.xから2.10.1へのアップデート時に以下の様なエラーが出るケースがありました。

$ cd /PATH/TO/MAUTIC
$ php upgrade.php
Checking for new updates...updating to 2.10.1!
Extracting the update package...failed. Package could not be found!

コアのソースコードを見る限りでは、zipファイルの取得に失敗している様子です。

対応

Issueのコメントにて、「zip取れてないから、直接おいてやればいいよ」というコメントがありましたのでそれで対応しています。

$ wget https://github.com/mautic/mautic/releases/download/2.10.1/2.10.1.zip
$ mv 2.10.1.zip 2.10.1-update.zip
$ php upgrade.php
Checking for new updates...updating to 2.10.1!
Extracting the update package...done!
Moving files...done!
Clearing the cache...done!
Rebuilding the cache...done!
Applying migrations...done!
Cleaning up...done!

Success!

Mauticでは、{バージョン番号}-update.zipという命名規則でファイルがDLされます。(該当コードはこちら
ですのでzipファイルをDLして、その名前に変更してやることでアップデートスクリプトが問題なく実行される様になります。

そのほか

該当ファイルがある場合はDLせずにそのまま展開して実行していく様子です。
なのでリネーム時に最新版のバージョン名へ偽装すればバージョン指定のアップデートもできるのかもしれません。(おすすめはしませんが)

CLIでMauitcコアのバージョンを指定してアップデートする

諸刃の剣なのでまったくおすすめしませんが、できるのはできたのでメモ。
アドオンや運用時のローカルテストくらいにしか使えなさそうです。

手順

やり方は簡単で、古いバージョンのコアzipファイルを最新版のバージョン名で配置しておくだけです。

$ cd /PATH/TO/MAUTIC
$ wget https://github.com/mautic/mautic/releases/download/2.8.1/2.8.1.zip
$ mv 2.8.1-update.zip 2.10.1-update.zip
$ php upgrade.php
Checking for new updates...updating to 2.10.1!
Extracting the update package...done!
Moving files...done!
Clearing the cache...done!
Rebuilding the cache...done!
Applying migrations...done!
Cleaning up...done!

Success!

GUIからアクセスすると、2.8.1で動作していることが確認できます。

CLIからもアップデートが必要なバージョンであることを認識していることが確認できました。

# php app/console mautic:update:find
Mauticのバージョン 2.10.1 がダウンロード可能です。詳細は https://www.mautic.org/community/index.php/8475-2-10-1-released をお読みください。
アップデートするにはコマンドラインから'php app/console mautic:update:apply'を実行してください。

やっぱり最新版にしたい場合

偽装しているzipファイルを消してphp upgrade.phpを実行しましょう。
上記手順と同様にwgetなどで最新版のzipファイルを直接配置するのも1つです。

ただし

コアチームの意図している動きではないので、このアップデートで事故るケースの方がおそらく多いと思います。
Vagrant / Dockerなどの使い捨てにしてもいい環境で、バージョンを指定したテストしたい場合に使う程度にしてください。

2.9.2 -> 2.8.1 -> 2.10.1を試して出たエラー(一部)

# php app/console doctrine:migrations:migrate

  [Doctrine\ORM\Mapping\MappingException]
  Duplicate definition of column 'id' on entity 'Mautic\CoreBundle\Entity\MessageQueue' in a field or discriminator column mapping.

]# tail app/logs/mautic_prod-2017-10-25.php
[2017-10-25 17:25:07] mautic.ERROR: Symfony\Component\Debug\Exception\FatalErrorException: Notice: require(): Failed opening required '/var/www/html/app/cache/prod/doctrine/orm/Proxies/__CG__MauticStageBundleEntityStage.php' (include_path='.:/usr/share/pear:/usr/share/php') - in file /var/www/html/vendor/doctrine/common/lib/Doctrine/Common/Proxy/AbstractProxyFactory.php - at line 209 [] []
$ tail -f /var/log/httpd/ssl_error_log
[Wed Oct 25 08:30:26.615227 2017] [:error] [pid 3345] [client 210.170.194.219:52779] PHP Warning:  require(/var/www/html/app/cache/prod/doctrine/orm/Proxies/__CG__MauticStageBundleEntityStage.php): failed to open stream: No such file or directory in /var/www/html/vendor/doctrine/common/lib/Doctrine/Common/Proxy/AbstractProxyFactory.php on line 209, referer: https://13.114.212.68/s/login
[Wed Oct 25 08:30:26.615264 2017] [:error] [pid 3345] [client 210.170.194.219:52779] PHP Fatal error:  require(): Failed opening required '/var/www/html/app/cache/prod/doctrine/orm/Proxies/__CG__MauticStageBundleEntityStage.php' (include_path='.:/usr/share/pear:/usr/share/php') in /var/www/html/vendor/doctrine/common/lib/Doctrine/Common/Proxy/AbstractProxyFactory.php on line 209, referer: https://13.114.212.68/s/login

そもそも

最新版で動く様に使って欲しいなと思う次第です。

Mautic1.4.1から2.x系にアップデートする

Mauticを触っていると、以下の様なコマンドがあったり、管理画面で「Mauticアップデートしませんか?」という案内と共にアップデートボタンが表示されたりと、WordPressなどに近い感じで気軽にアップデートできるようになってます。

$ php app/console help mautic:update:apply

ただ、1.x系から2.x系へのアップデートに関してはどちらも絶対に使っちゃダメです。

リリースノートにもバッチシ「使うな」って書かれてます。

Our CLI command, php app/console mautic:update:apply WILL NOT WORK
https://github.com/mautic/mautic/releases/tag/2.0.0

これを知らずにアップデートを実行してしまうと、非常につらい思いをします。万が一やっちゃったという人は、Mautic1.4.1をぶっ飛ばしたときの復旧メモを参考に一旦復旧させましょう。というかアップデートはマジでバックアップとってからやりましょう

1.x系から2.x系へのアップデート方法

じゃあどうやってアップデートすれば良いのかですが、上記のリリースノートを読むと「このファイルを実行してくれ」という案内があります。

We have provided an upgrade script to use instead. Please download this script from https://raw.githubusercontent.com/mautic/mautic/master/upgrade.php, place in the root of your Mautic installation, and run it from CLI with php upgrade.php. It will fetch 2.0.0 and proceed to upgrade your Mautic installation.

https://github.com/mautic/mautic/releases/tag/2.0.0

こいつを使ってアップグレードしましょう。

実行した環境

今回は、Mautic Powered by AMIAGEで作られたMauticを使用しています。

実行ユーザーなどが異なる可能性がありますので、他の環境で実行される際はご注意ください。

実行コード

$ cd /var/www/html
$ sudo mv upgrade.php /tmp
$ sudo wget https://raw.githubusercontent.com/mautic/mautic/master/upgrade.php
$ sudo php upgrade.php
$ sudo chown -R apache:apache ./
$ sudo rm 2.1.1-update.zip