Mac の CLI からの PHP で MySQL に接続できない不具合を解決することができなかった

Mac の Lion で Shell から処理を実行しようとしたら以下のようなエラーが出ました。

1
2
PHP Fatal error:  Call to undefined function mysql_query() in /var/www/cakephp/cake/libs/model/datasources/dbo/dbo_mysql.php on line 609
Fatal error: Call to undefined function mysql_query() in /var/www/cakephp/cake/libs/model/datasources/dbo/dbo_mysql.php on line 609

昔は動いてたので Lion にしたのが原因か、私が最近行った変更が原因の可能性があります。で、結局解決できなかったんですが、調べていくうちにいろいろと勉強になったので後から自分が見るためにブログに残しておくことにしました。

ちょっとしたパスの変更で簡単に対応できるに違いない

調べたところ以下のサイトが参考になりそうだと思ったので参考にしつつ調べてみることにしました。

php.ini とかに関係があるのでしょうか。とにかく PHP の設定を確認します。

1
php -ini

CLI では php.ini を読み込んでいないようなので、オプション -c で php.ini を指定して実行してみます。こんなオプションで好きな php.ini を読み込むことができるんですね。

1
php -c /etc/php.ini /var/www/cakephp/cake/console/cake.php system update -app /var/www/cakephp/app

それでも同じエラーが出続けます。そもそも /tmp/mysql.sock が一般的なのに対して私の環境では /opt/local/var/run/mysql5/mysqld.sock しかない。MySQL で status をしてもこちらが設定してあるような状態です。

dll ファイルを読み込んでないのが原因に違いない

dll ファイルが無いからかと思いましたが、Mac では dll ファイルで設定するわけではないらしいので違うようです。

みんなと同じ mysql.sock を作成すれば良いに違いない

じゃあ mysql.sock を作成すればいいのだろうかということで作成方法を調べると、以下のサイトでは再起動すれば作成されるとのことです。

さっそく MySQL の再起動を行って見ることにしましたが、Mac での MySQL の再起動方法が分かりません。Mac の MySQL の再起動方法については以下のページが参考になります。

1
2
sudo /opt/local/share/mysql5/mysql/mysql.server stop
sudo /opt/local/share/mysql5/mysql/mysql.server start

そして /tmp/mysql.sock が存在するか確認したところやはり存在しません。私の知識ではこの辺りまでしかどうにかなりませんので、ここまできたら何でもやってみるしか無いです。

PHP をフルパスで実行すれば良いに違いない

以下の記事では PHP をフルパスで動かしていたので私も挑戦。

1
/opt/local/bin/php -c /etc/php.ini /var/www/cakephp/cake/console/cake.php system update -app /var/www/cakephp/app

これでも結局動きませんでした。ここで phpinfo() をしっかりと見直すと、普段は MySQL の項目があるのに対して CLI から実行すると MySQL の項目がありません。何を読みこめば CLI から MySQL を使えるようにできるのかな。

/tmp/mysql.sock を作成できる手がかりを発見

しばらく調べていると以下の記事で /tmp/mysql.sock はセーフモードで起動させることで作成されるらしいとのことでチャレンジ。

しかし mysqld_safe コマンドがないので find で調べます。すると
/opt/local/lib/mysql5/bin にあるようです。ここにも普段からパスを通しておくのが一般的なんでしょうか。Lion にすると中途半端にアップグレードしていてとても爽快です。

1
2
sudo /opt/local/share/mysql5/mysql/mysql.server stop
sudo /opt/local/lib/mysql5/bin/mysqld_safe

すると何もできなくなるので別のターミナルを開いて MySQL にコマンドラインからログインすると作成されるらしい。

1
mysql -u root -p

しかし私の環境では何も作成されず。

パスを環境に合わせて変更しちゃえば動くに違いない

/tmp/mysql.sock も /var/mysql/mysql.sock もないし、とりあえず php.ini の mysql.sock の部分は全て /opt/local/var/run/mysql5/mysqld.sock に変更しました。また、先日 MeCab の設定の際に my.cnf がなかったので、どこからら cp でコピーして持ってきたと思うので、こちらも削除して MySQL と Apache を再起動しましたが、それでも何も変わらない。

my.cnf に問題があるに違いない

my.cnf の設定を弄ればなんとかできるかもしれないと思ったので試してみることにしました。まず、以下のコマンドで my.cnf の関連ファイルを表示してみます。

1
sudo find / -name 'my*.cnf

以下のような socket ファイルが一覧されます。

1
2
3
4
5
/opt/local/share/mysql5/mysql/my-huge.cnf
/opt/local/share/mysql5/mysql/my-innodb-heavy-4G.cnf
/opt/local/share/mysql5/mysql/my-large.cnf
/opt/local/share/mysql5/mysql/my-medium.cnf
/opt/local/share/mysql5/mysql/my-small.cnf

中身を見てみましたが、sock ファイルの場所は全部同じです。やはりこれで正しいのでしょうか。皆さんはなぜ /tmp/mysql.sock が設定されてるんでしょうか。

一歩前進 /tmp/mysql.sock を作成することに成功

試しに既に使っている /etc/my.cnf の socket を /tmp/mysql.sock に変更してみることにします。それで /tmp/mysql.sock が生成されて上手くいくことを狙います。複雑な作業なので頭の整理のために作業を箇条書き。

  1. /etc/my.cnf の socket パスを /tmp/mysql.sock に変更
  2. MySQL を停止してセーフモードで起動後ログイン
  3. /tmp/mysql.sock が生成されたことを確認
  4. ログアウト後 MySQL を停止して通常起動をします
  5. ブラウザから MySQL に接続できなくなったことを確認
  6. /etc/php.ini の socket の部分を /tmp/mysql.sock に変更
  7. Apache の再起動
  8. ブラウザから MySQL に接続できることを確認できたが CLI から実行した PHP からは MySQL に接続できないことを確認

やはり問題解決には至りませんでしたが、my.cnf に設定したパスに従って MySQL に接続するためのソケットファイルを生成してくれるということが分かりました。このソケットファイルの名称の違いが気になるところではありますが、要はこれにパスを通せば PHP からは接続できる、

そして CLI もそれが言えるのではないか。もしかしたら CLI で php.ini を読み込めてると行っても、結局はこの /tmp/mysql.sock を使えない理由があるのではないか、いろいろ考えながら挑戦してみることにします。

隠された php.ini の設定欄がある説

CLI からの PHP からの MySQL への接続するための設定欄があってまだそこを設定していない。

ちなみに MeCab などの拡張モジュールは CLI からでも読み込めているので、php.ini への接続はある程度できているからこそ、MySQL の設定が抜けているに過ぎないはずだと思いました。

TimeMachine を使って正常に CLI から MySQL に接続できていた過去の php.ini と現存の php.ini を調べまくりましたが、MySQL の設定欄はどこにもありませんでした。どうやら php.ini には全く問題がないと言っても良いのかもしれません。

phpinfo() の結果はフェイクである説

CLI から PHP を起動するときに -c オプションで php.ini を明示的に読み込んでるとはいえ、実は読み込んではないのかもしれない。phpinfo() の結果では php.ini を読み込んでるような表示があるけど実はフェイクなんじゃないか。

GUI から実行した phpinfo() の結果は以下です。

Configuration File (php.ini) Path /etc
Loaded Configuration File /private/etc/php.ini

CLI から実行した phpinfo の結果は以下です。

1
2
Configuration File (php.ini) Path => /opt/local/etc/php5
Loaded Configuration File => /private/etc/php.ini

読み込んでると見せて、結局読み込めていないんじゃないか。少しでも気になるところは変えていこうと思います。ただ Configuration File (php.ini) Path を変更する方法が少し探しても見つからないので、検証のためだしファイルをコピーして置いてみることにします。

1
2
3
cd /opt/local/etc/php5
sudo mv php.ini php.ini.old
sudo cp /etc/php.ini /opt/local/etc/php5/php.ini

関係ないと思いますが、Apache を念のために再起動。ついでに GUI から PHP を実行して MySQL への接続を確認。そして CLI での実行で失敗しました。明示的に -c オプションで指定していた /etc/php.ini を外して実行しても失敗。

PHP ファイルで直接指定すれば動くはず

php.ini は読み込めている、php.ini の記述も問題ない。どうしたものかと思っていたら PHP で直接設定することができるようなのでこちらにチャレンジしてみることにしました。

1
ini_set("mysql.default_socket","/tmp/mysql.sock");

これでもやはり同じエラーが出てしまいました。ここまで来て今回の問題は、socket も原因ではあったけど、この部分についてはもう既に解決できていて、今は他のところに問題があるんだなと思いました。

パーミッションに問題があるのに違いない

Twitter で教えて頂きましたが、以下のサイトにパーミッションに問題があるとのことが書いてありました。挑戦してみます。

ちなみにどのファイルが該当のファイルか分からないので find で調べてみると以下のような構成であることが分かります。これを一つずつチェックしていきます。

1
2
3
4
5
6
/opt/local/bin/mysql
/opt/local/include/mysql5/mysql
/opt/local/lib/mysql5/bin/mysql
/opt/local/lib/mysql5/mysql
/opt/local/share/mysql5/mysql
/opt/local/var/db/mysql5/mysql

全て検証しましたが、パーミッションの問題ではありませんでした。ちなみに全て 755 でした。

最後に

力尽きました。何が原因だったか分かりませんが、Ubuntu 構築してそこで動作させるにしました。開発用サーバーはそのためだけに構築した方が良さそうですし、用途に合わせてサーバーって設定が変わるので、もうこれでいいかなと思います。

追記: 原因について

Twitter でギークな方達にアドバイス頂きました。

PHPにMySQLライブラリが入ってないのでPortsとかで再コンパイルして入れればいいんでは?php -r ‘phpinfo();’ | grep mysqlで何も出ない気が

mysql_query() の定義自体無いというエラーですと, make の前の ./configure で MySQL モジュールを有効にできていないように思えます.

とのことです。再コンパイルすれば良いようです。いろいろ動かなくなってるので再コンパイルもそうですし、PHP もライブラリなども全部入れ直したいと思います。

コメント

コメントは受け付けていません。