質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PDO

PDO(PHP Data Objects)はPHPのデータベース抽象化レイヤーです。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

CakePHP

CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

Q&A

解決済

1回答

2746閲覧

外部コマンド経由での Shell 処理で DB へのアクセスができない

keiji44

総合スコア18

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PDO

PDO(PHP Data Objects)はPHPのデータベース抽象化レイヤーです。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

CakePHP

CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

1グッド

1クリップ

投稿2016/11/15 16:57

編集2016/11/16 01:13

###環境
Windows10 / Apache 2.4系 / MySQL 5.5系 / CakePHP 2.7.5
###前提・実現したいこと
CakePHPで特定のURLでのアクセスをトリガーとした、非同期でのバッチ処理を実装しています。
処理の流れは以下の通りです。

  1. http://ドメイン/batch/action/{$method} にアクセス

{$method} は実行する function 名
2. BatchesController 内の function action 内で、
"Console\cake batch {$method}" を非同期で実行
具体的には popen("start Console\cake batch {$method}", "r") という形で、
外部コマンドを利用して start で非同期を実施します。
3. BatchShell 内に定義した function {$method} に処理を記載

###発生している問題・エラーメッセージ
BatchShell 内の function {$method} 内で DB へのアクセスが発生するプログラムがあるのですが、
どうやら、DB の設定情報が取得できないようで、DB へのアクセスができない状態が発生しています。
以下のエラーメッセージを確認しました。

Database connection "Mysql" is missing, or could not be created.

コマンドプロンプトを立ち上げて、
Console\cake batch {$method} と直接実行すれば正常に動作するので、
popen を経由することで発生しているような気がします。

exec、system 等、他の外部コマンドでも上記のエラーメッセージが表示されたので、
外部コマンド経由での実行が原因かもしれない、というところまでは分かっています。

###試したこと
BatchShell 内の function {$method} 内で $this->log("hoge"); とすると、
ログには出力されるので、function {$method} までは処理が到達しています。

ただ、以下のような DB へのアクセスが発生するようなプログラムを書くと上記のエラーメッセージが表示されます。
$this->{Model}->{function}; (実際に存在する関数)

DB の接続情報はどうなっているのかと思い、
以下も試してみましたが、同様に上記のエラーメッセージが表示されます。
・$this->{Model}->getDataSource();

ソースを追いかけていくと、Mysql.php 内の以下の function 内に原因がありました。

public function enabled() { return in_array('mysql', PDO::getAvailableDrivers()); }

コマンドプロンプトからの直接実行では、
PDO::getAvailableDrivers() の中身が以下になるのに対して、

Array ( [0] => mysql [1] => odbc )

popen 経由で実行すると PDO::getAvailableDrivers() の中身は空になっていました。

なぜ popen 経由では PDO::getAvailableDrivers() が空になるのかが分かれば解決しそうなのですが、
ネットで色々情報を探しても解決策が見つからず八方ふさがり状態です。

お知恵を拝借していただければありがたいです。


追加で、以下の2つファイルを用意して検証しました。

・check_pdo.php

<?php echo '<pre>'; var_dump('ACTION!'); // この文字列が表示されれば check_pdo.php 自体は実行されている var_dump(PDO::getAvailableDrivers()); echo '</pre>'; ?>

・check_pdo_via_popen.php : chekc_pdo.phppopen で呼び出すファイル

<?php $cmd = 'php {ファイルまでのパス}/check_pdo.php'; $fp = popen($cmd, 'r'); print '<pre>'; while ($read = fread($fp, 2096)) { echo $read; } print '</pre>'; pclose($fp); ?>

コマンドプロンプトから check_pdo.phpphp コマンドで直接実行

実行コマンド
C:\Windows\SysWOW64> php {ファイルまでのパス}/check_pdo.php
※ php のパスは通してあります。

結果

<pre>string(7) "ACTION!" array(2) { [0]=> string(5) "mysql" [1]=> string(4) "odbc" } </pre>

Web ブラウザから直接 check_pdo.php にアクセス(CakePHP は経由せず)

結果

string(7) "ACTION!" array(2) { [0]=> string(5) "mysql" [1]=> string(4) "odbc" }

コマンドプロンプトから check_pdo_via_popen.phpphp コマンドで直接実行

実行コマンド
C:\Windows\SysWOW64> php {ファイルまでのパス}/check_pdo_via_popen.php
※ php のパスは通してあります。

結果

<pre><pre>string(7) "ACTION!" array(2) { [0]=> string(5) "mysql" [1]=> string(4) "odbc" } </pre></pre>

Web ブラウザから直接 check_pdo_via_popen.php にアクセス(CakePHP は経由せず)

結果

string(7) "ACTION!" array(0) { }

コマンドプロンプトからであれば popen を利用しても表示されたので、
原因は popen ではないようです。

最初の質問と共通するのは Webブラウザからアクセスだと空になる ということですので、
Apache ユーザで実行すると特定の条件下で発生する?辺りなのかと踏んでいます。

引き続き、よろしくお願いします。

KiyoshiMotoki👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

popobot

2016/11/15 21:56

切り分けとして、cakephpではなくphpでPDO::getAvailableDrivers()をやったらどうなりますか?
keiji44

2016/11/16 01:07

回答ありがとうございます。追加で検証した内容を追記しました。
guest

回答1

0

ベストアンサー

手元の環境でブラウザからcheck_pdo_via_popen.phpを実行したらMySQL見れました。
※ただしLinux + Nginxですが...。

なんとなく、phpの実行環境(設定)が違うのかなぁと...(PHP自体が違う?)
check_pdo.phpにphpinfo();を追記して同じようにやった場合、phpの情報がどう違うか見てみるといいかもしれません。

投稿2016/11/16 01:30

編集2016/11/17 02:39
popobot

総合スコア6586

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

keiji44

2016/11/16 02:51 編集

ご指摘、ビンゴでした! PDO::getAvailableDrivers() が空になる場合に、 古い PHP のバージョン(※)が表示されました。 ※ 最初にこの環境にモジュール版として PHP をインストールしたバージョン : 5.3.8 ※ 逆に正常に実行されるときは 5.6.15 この環境では複数の PHP が使用できるようにしてあります。 (Apache で fcgi を使用、 Virtualhost でドメイン毎に php の実行パスを分けています) https://teratail.com/questions/9842 ここを見ると、Linux での内容ではありますが、 外部関数での実行と、WEBサーバ経由での実行では、異なる PHP を参照するとあるので、 Windows ではありますが、これと同じことが起きているようです。 結局、Console\cake.bat 内の php コマンドを実行している個所を、 フルパスで指定したら動くようになりました。 この Windows 環境は開発環境ですので、 取り急ぎ、これで乗り切りたいと思います。 ありがとうございました。
popobot

2016/11/16 02:58

なるほど! 解決して良かったです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問