Could not open input file
一見よさそうだけど、引数の処理がうまくいかないので、この記事は前面削除です。
症状
Cygwin+bash 上で、次のような php スクリプトを実行するとエラーになりました。
#! php <?php print "Hello"; ?>
$ hello.php Could not open input file: /home/egc/bin/hello.php
対策
本当のphpインタプリタ(c:/php/php.exe)のダミー php(.sh)を作って、ダミーを経由させて、パス形式を変換して実行させます。
まず path を確認しておきます。
例えば、phpインタプリタが c:/php/php.exe、ユーザ用のbinフォルダが /home/egc/bin として、
$ echo $PATH ・・・:/home/egc/bin:・・・:/cygdrive/c/php:・・・
のように path の並びは、ユーザー用の/home/egc/binが先行しているはずです。ダミーのphpはユーザー用のbinに置きます。
ダミー「php」スクリプト
本物のphpインタプリタ(c:/php/php.exe)よりも優先されるパスに置きます(/home/egc/bin/php)。
#! /usr/bin/sh php.exe $(cygpath -m "$1")
実行すると...
$ hello.php Hello
えーと、
- bashのシェルコマンドから、hello.php を実行すると、
- 1行目の#! phpに従ってシェルが php を起動しますが、
- パスで先行するダミーの php が起動されて
- cygwin風のパスをミックス(-m)形式に変換し、
- 本当のphpインタプリタ(php.exe)を実行
というからくりになります。
ちなみに、hello.php はここでは、/home/egc/bin に置いてますが、どこにおいても問題はありません。そのときは、./hello.php などと起動します。
うーん。もっと上手い方法がないものでしょうか・・・
補足 php.ini
軽量化した php.ini を使う場合、環境変数で「PHPRC=c:/home/egc/bin」として、php.ini のサーチフォルダを指定することができますが、それだと常に「c:/home/egc/bin/php.ini」が使われることになります。そこで、各々のスクリプトでべつの INIファイルが使えるようにする方法を検討します。
軽量化した独自のCLI用のINIファイルのパスを「c:/home/egc/bin/my.php.ini」とします。このINIファイルの内容は次のようだとします。
[PHP] extension_dir = "c:/php/ext" extension=php_sockets.dll extension=php_mbstring.dll
PHPスクリプト(c:/home/egc/bin/hello.php)は次のように書きます。
#! php -c my.php.ini <?php print "Hello"; ?>
関連するファイルの構成は次のようになります。
c:/ ├ php/ │ ├ dev/ │ ├ ext/ │ ├ PEAR/ │ ├ php.exe <=本物のphpインタプリタ実行ファイル │ └ php.ini <=デフォルトのINIファイル │ ├ home/egc/bin │ ├ php <=ダミーのphp。CLI専用 bash スクリプト │ ├ my.php.ini <=軽量化したINIファイル │ └ hello.php <=任意のPHPスクリプト
この hello.php は、「my.php.ini」が置かれている「c:/home/egc/bin」フォルダでしか実行できません。どのフォルダからでも実行できるようにするには、INIファイルを絶対パスで指定する必要があります。つまり、「#! php -c c:/home/egc/bin/my.php.ini」とするのですが、これはうれしくないので、phpを改変します。
#! /usr/bin/sh function argproc { while [[ $# -gt 1 ]] do case $1 in -c) echo "$1" shift echo $(cygpath -m "$(dirname $0)/$1") ;; *) echo -n "$1 " ;; esac shift done echo $(cygpath -m "$1") } args=$(argproc $@) php.exe $args