PHP プロセス置換のファイルが読み込めない

この記事では、PHPスクリプトで、
プロセス置換されたファイルが、読み込めない時の対処方法を、記載します。

プロセス置換とは

プロセス置換 (Process substitution) とは、
シェルの機能で、コマンドの出力結果を、
ファイルとしてコマンドライン引数に、わたす事ができる機能です。
Bashや、Zshなどで、利用することができます。

例えば、
コマンドライン引数で、ファイルを一つ受け取る、
PHPスクリプトがあったとして。
複数のファイルを、合成してから渡す場合、下記のようになります。

# a.txt b.txt をあらかじめ合成して、c.txtを作成
cat a.txt b.txt > c.txt

# 作成したc.txtをコマンドライン引数で渡す
php sample.php c.txt

これが、プロセス置換を利用すると、
合成するために生成した c.txtというファイルを、作成しなくても
直接 sample.php に、指定することができます。

# プロセス置換で、直接渡すことができる。
php sample.php <(cat a.txt b.txt)

fopen関数

fopen ($filename , $mode)
指定のファイルを開き、ファイルハンドルを返す、PHPの関数。

$fp = fopen($argv[1], "r");

コマンドライン引数で、指定されたファイルをオープン。

エラーが発生する場合がある

しかし、プロセス置換を使って、指定したファイルだと
下記のように、エラーが発生する場合があります。

PHP Warning: fopen(/dev/fd/63): failed to open stream: No such file or directory

これは、PHPのバージョンが古い為に、発生するエラーです。

対処法

PHPバージョンを上げる

ローカル環境など、自分で自由に、更新できる環境であれば、
PHPのバージョンを上げるのが、一番良いです。

どのバージョンから、この現象が修正されているのか、詳しくはわからないですが、
私の環境で発生するバージョンと、発生しないバージョンが確認できたので、
ここに記載しておきます。

  • エラーが出るバージョン

    $ php --version
    PHP 5.4.45 (cli) (built: Jan 11 2019 13:55:19)
    Copyright (c) 1997-2014 The PHP Group
    Zend Engine v2.4.0, Copyright (c) 1998-2014 Zend Technologies
  • 正常に動作するバージョン

    $ php --version
    PHP 5.6.30 (cli) (built: Oct 29 2017 20:30:32)
    Copyright (c) 1997-2016 The PHP Group
    Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies

PHP Stream Wrapper にリプレースする

古いバージョンのPHPを、使い続けなければならない場合、
PHP Stream Wrapper を利用して、スキーマにリプレースすることで、
正しく動作させることができます。

$filename = $argv[1];
$fp = fopen(str_replace('/dev/', 'php://', filename), "r"); 

プロセス置換されたファイルは、
/dev/fd/63のように、/dev/から始まるパスになります。
これを、"php://" というスキーマにリプレースすることで、
読み込みできるようになります。

まとめ

プロセス置換とは、シェル(Bash, Zshなど)の機能で、
コマンドの出力結果を、一時的なファイルにして、
コマンドライン引数として、渡す事ができる。

古いバージョンのPHPだと、
プロセス置換で渡されたファイルを、fopenで開けない。

PHPバージョンを更新するか、
PHP Stream Wrapper で、"php://"スキーマにリプレースすると、
正しく読み込めるようにできる。

1件のコメント

コメントを残す