PHPをコマンドライン(CLI)から実行するとエラー

作成したPHPファイルをcronなどで実行させる場合、PHPをコマンドライン(CLI)から指定することになりますが、これが思わぬ障害になることがあります。

あれ?ブラウザからアクセスしたら動くよ?

そうなのです。ブラウザからそのPHPファイルにアクセスするとちゃんと動くのですが、これがコマンドからの指定となると以下のようなエラーが表示されてしまうのです。

# /usr/bin/php  /(phpファイルまでのパス)/script.php
PHP Warning:  include_once(../../config.php): failed to open stream: No such file or directory in /(phpファイルまでのパス)/script.php on line 16
PHP Warning:  include_once(): Failed opening '../../config.php' for inclusion (include_path='.:/php/includes:/usr/share/pear') in /(phpファイルまでのパス)/script.php on line 16
...(以下略)...

「あー、時間がないからすぐに解決策を!」という方はページの一番下に行っちゃってください。笑 理由を知りたい方はそのまま読み進めてください。

外部ファイルの相対パス指定読み込みに注意!

エラーを見てみると、どうやらそのスクリプトファイルの中で相対パス指定の外部ファイルを読み込もうとしたところでエラーが発生しています。 これはどうしてかというと、スクリプトファイルを実行している「現在のディレクトリ」情報がブラウザとコマンド実行とで異なるからなのです。

ブラウザでは、スクリプトファイルにアクセスした時点でそのスクリプトファイルのあるディレクトリが現在のディレクトリということになるので、相対パス指定で「../../config.php」というのはスクリプトファイルよりも2階層上の「config.php」ということで、私の作成したconfig.phpはそこに存在しますので、問題なく読み込まれます。

ところが、cronで同じように指定すると、cronの実行ユーザーに依存するようになります。

cronをroot権限で実行する場合、「現在のディレクトリ」は「/root/」になります。 ですので「include_once(../../config.php)」という指定をしてしまうと、「/root/」よりも2階層上ということで、当然そんな階層にファイルがあるわけがないので、最初に書かれたエラーが表示されてしまいます。

ちなみに、cronが実行されている際の「現在のディレクトリ」を知る方法は以下の実行指定を書いておくと、1分後に/tmp/getcwd.txtに書いてあります。

# crontab -e
-------------------------------------------------
...(前略)...
*       *       *       *       *       /usr/bin/php -r "print(getcwd());" >/tmp/getcwd.txt
-------------------------------------------------

確認できたらcronの記述と/tmp/getcwd.txtファイルを削除しておいてくださいね。

さて、話を元に戻して…このエラーはどうすれば良いのでしょうか?

該当のディレクトリに移動して解決

解決策は、実行するスクリプトファイルの階層まで移動してから実行すると良いでしょう。

例えば、いままでcrontabに以下のように書いていたとします。

10 * * * * /usr/bin/php /(phpファイルまでのパス)/script.php

これを以下のように書き換えます。

10 * * * * cd /(phpファイルまでのパス)/; /usr/bin/php script.php

これで無事動くようになったのではないでしょうか。

このページをシェアする

2009-09-08