Posted by & filed under PHP, Tech.

peel back the layers...there sits the shell
peel back the layers…there sits the shell / blakespot

久しぶりに CodeIgniter をさわりまして。

なにかしらの cron ジョブを実行させようとしたときにちょっとコケました。コマンドラインからコントローラ呼び出し実行が出来なかった(正確には URL 文字列取得の失敗)わけであります。

事案発生率としては低め?わたくしもたまたま動かしていたレンタルサーバ: XSERVER でのみ発生を確認したのですが、WEB にも特に解決策がなさそうだったので作業録として残しまっす。

ads

 

運用状況

言語: php 5.3
フレームワーク: CodeIgniter 2.1.3
サーバ: XSERVER X10プラン

 

やろうとしていたこと

前出のとおり、XSERVSER 上で動く CodeIgniter アプリケーションで、コマンドラインからのコントローラ呼び出しを試みました。コマンドラインから PHP を実行する理由として、多くの場合バッチ処理とか、バックグラウンド処理をやりたい場合でしょうかね。

仮に、batch というコントローラを作り、index メソッドで echo するだけのプログラムを作ってみます。

<!--?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
 
class Batch extends CI_Controller {
    public function __construct() {
        parent::__construct();
    }
 
    public function index() {
        echo 'Hello from CLI!';
    }

 

いきなり結論!

長くなりそうなので先に結論をお知らせしておきます。

CLI からPHP を実行する場合、通常は PHP 実行ファイルパスを指定しますが、XSERVER 上で使用している実行ファイル(この場合は /usr/bin/php5.3) ではなく、CLI 用(?)の実行ファイルである /usr/bin/php-cli を指定する必要がございました。

/usr/bin/php5.3 ./index.php batch

ではなく

/usr/bin/php-cli ./index.php batch

を指定してやる必要があるようです。

以下、実際の調査内容と、この件を XSERVER カスタマーサポートに問い合わせた流れを書きなぐっていきたいと思います。お時間あればお付き合いください~

 

CLIから実行すると、指定したコントローラが呼び出されない!

XSERVER のサーバ情報に則り、PHP のパスは /usr/bin/php5.3 を指定して、たった今作成した batch コントローラを呼び出します。CLI からの実行方法は、CodeIgniter のユーザガイド「やってみましょう: Hello World!」より。

/usr/bin/php5.3 ./index.php batch

Oops!なんだいこれは!どうやら CodeIgniter に設定しているデフォルト URL の HTML がコンソール上に出力されてるじゃあないか!ひー

 

何が問題なのか

何が原因なのかさっぱりだったので、CodeIgniter の中身を index.php から順を追って探索!なんとなくURLまわりかな~っと目星をつけつつ。

まず index.php 内、特に何事もなく一番最後に /system/core/CodeIgniter.php を読み込んで終了。
次に CodeIgniter.php を探索します。ざっと眺めていくと169行目、ルーティングの設定個所を発見。

/*
 * ------------------------------------------------------
 *  Instantiate the routing class and set the routing
 * ------------------------------------------------------
 */
    $RTR =& load_class('Router', 'core');
    $RTR->_set_routing();

というわけで、$RTR->_set_routing() が使われている /system/core/Router.php を探索。
_set_routing メソッド内154行目、URL string をフェッチしている個所を発見。

// Fetch the complete URI string
$this->uri->_fetch_uri_string();

名前的に URL がどうなってるかわかるだろう、と _fetch_uri_string() が使われている /system/core/URI.php を探索。
すると89行目、config ファイルで設定出来る uri_protocol が ‘AUTO’ である場合に実行する if 構文内で CLI に関するっぽいのを発見!

// Is the request coming from the command line?
if (php_sapi_name() == 'cli' or defined('STDIN'))
{
    $this->_set_uri_string($this->_parse_cli_args());
    return;
}

コマンドラインから来た? Yes, certainly! ここで true であれば CLI からのリクエストを理解してもらえるんでしょう、と条件文で使われている関数 php_sapi_name()defined(‘STDIN’) を地道にダンプする。

 

/usr/bin/php5.3 ./index.php batch

結果は

  • php_sapi_name() -> string(8) “cgi-fcgi”
  • defined(‘STDIN’) -> bool(false)

し、 cgi-fcgi ?と、まさしくCLI からのアクセスを認識されていない状況。

なぜだ?! コマンドラインから実行した場合、 php_sapi_name() の戻り値は ‘cli‘ じゃあないのかい?そして STDIN はなぜ設定されていないのだい?

というわけで、XSERVER 上で動かしている PHP で CLI から実行した場合、CLI からのアクセスであることを認識されない流れとなりました。

 

おしえて!なかのひと!

このままではらちがあかないので XSERVER のカスタマーサポートさんにこの事案を問い合わせてみました。
以下、カスタマーサポートさんとのやりとりを抜粋。

Q. CLI からのリクエスト時、 php_sapi_name() の戻り値が cli でないのは何故でしょう?
A. エックスサーバーでは PHP のご利用に際して、モジュール版ではなく CGI 版を提供しております。

なんですと、、するってぇと XSERVER では php_sapi_name() の戻り値判定で CLI からのリクエストを認識することは出来ないのか。
では STDIN の定数はどうなってるんだろう。とよくわからないまま続けて質問。

Q. サーバに STDIN 定数が設定されていないのは、PHP が CGI 版であることに影響しますか?
A. 弊社サーバーの現在の設定の関係から、「usr/bin/php5.3」にて STDIN 定数はご利用いただけません。また、サーバー設定変更の予定も現在のところ無い状況でございます。

とのことでした。

 

XSERVER 上で CodeIgniter を CLI から利用するにはどうする?

困ったな、と XSERVER の PHP 実行ファイルが格納されているディレクトリを見ていたら、見慣れぬ php-cli を発見。WEB上のコントロールパネルから PHP のバージョンを気軽に変更出来る XSERVER ですが、こんな名称のは見たことない!ものは試しでこの PHP を指定して CLI から実行してみました。

/usr/bin/php-cli ./index.php batch

結果は

  • php_sapi_name() -> string(3) “cli”
  • defined(‘STDIN’) -> bool(true)

ぉお!成功!意図する動きを実現。ひとまずこれを使えば XSERVER 上で CodeIgniter アプリケーションに CLI からのリクエストが成功しました!

 

再びおしえて!なかのひと!

Q. php-cli ってのを見つけたので使ってみたら意図する動きでした!使って問題ないですか?
A. 「/usr/bin/php-cli」をご利用いただくことは何ら問題はございません。ご利用については可能ではございますが、公式的なサポートをいたしておりません。エラー等生じた場合のサポートは対象外事項となりますため、予めご了承いただきますよう、よろしくお願いいたします。

なるほど、わかりやした~!ってな流れで問いあわせ終了。

 

まとめ

XSERVSER 上で CodeIgniter アプリケーションを運用する、CLI からのリクエストを前提としている場合、

  • PHP は CGI 版が提供されている
  • STDIN 定数はご利用いただけない
  • 最悪動かせないことはない

という3つの点に気をつけつつ動かしましょう!ってことですかな。

XSERVER はレンタルサーバにも関わらず低価格・高性能であったりマルチドメイン無制限であったり、ssh ログイン出来たり cron 設定も比較的自由だったり、と魅力的ではありますが、やはりレンタルサーバというところで影響を受ける部分もありますね。

ひとまずわたくしめの場合は /usr/bin/php-cli を使うことで切り抜けました。

 

補足

CLI からのリクエスト判定には、CodeIgniter ユーザガイドにもあるように $this->input->is_cli_request() の関数を使うことで実現出来ますが、判定方法が同じように

  • php_sapi_name()
  • defined(‘STDIN’)

の戻り値で判定しています。というわけで、/usr/bin/php-cli を使わないと判定ミスりますのでご注意を。

Related Posts Plugin for WordPress, Blogger...

Leave a Reply

  • (will not be published)