web-dev-qa-db-ja.com

相対パスがcronで機能しないPHPスクリプト

PHPスクリプトがcronスクリプトとして実行されている場合、相対パスが使用されているとインクルードが失敗することがよくあります。たとえば、

require_once('foo.php');

ファイルfoo.phpは、コマンドラインで実行したときに見つかりますが、cronスクリプトから実行したときは見つかりません。

これに対する一般的な回避策は、最初に作業ディレクトリにchdirするか、絶対パスを使用することです。ただし、この動作を引き起こすcronとShellの違いは何ですか。 cronスクリプトで相対パスを使用すると失敗するのはなぜですか?

48
Sjoerd

スクリプトの作業ディレクトリは、cronから実行すると異なる場合があります。さらに、PHPのrequire()とinclude()についていくつかの混乱があり、作業ディレクトリが本当に問題であるという混乱を引き起こしました。

include('foo.php') // searches for foo.php in the same directory as the current script
include('./foo.php') // searches for foo.php in the current working directory
include('foo/bar.php') // searches for foo/bar.php, relative to the directory of the current script
include('../bar.php') // searches for bar.php, in the parent directory of the current working directory
12
Sjoerd

作業ディレクトリを実行中のファイルパスに変更します。使うだけ

chdir(dirname(__FILE__));
include_once '../your_file_name.php'; //we can use relative path after changing directory

実行中のファイル。その後、すべてのページですべての相対パスを絶対パスに変更する必要はありません。

97

"require_once"がcronとApacheを同時に使用できる唯一の機会は

require_once(dirname(__FILE__) . '/../setup.php');
7
jansch

Cronジョブの「現在の作業ディレクトリ」はcrontabファイルが存在するディレクトリになるため、相対パスはTHATディレクトリからの相対パスになります。

これを処理する最も簡単な方法は、dirname()関数とPHP ___FILE___定数を使用することです。それ以外の場合は、移動するたびに新しい絶対パスでファイルを編集する必要があります。別のディレクトリまたは別のファイル構造を持つサーバーへのファイル。

_dirname( __FILE__ )
_

___FILE___は、PHPによって呼び出されるファイルへのフルパスとして定義された定数です。ファイルが含まれている場合でも、___FILE___は常にファイル自体の完全パス-インクルードを行うファイルではありません。

したがって、dirname( __FILE__ )は、ファイルが含まれているディレクトリへの完全なディレクトリパスを返します。ファイルのインクルード元に関係なく、basename( __FILE__ )はファイル名自体を返します。

例:「/home/user/public_html/index.php」に「/home/user/public_html/your_directory/your_php_file.php」が含まれているとしましょう。

「your_php_file.php」でdirname( __FILE__ )を呼び出すと、アクティブなスクリプトが「/ home/user/public_html」にあるにもかかわらず、「/ home/user/public_html/your_directory」が返されます(末尾のスラッシュ)。

INCLUDINGファイルのディレクトリが必要な場合:dirname( $_SERVER['PHP_SELF'] )を使用すると、「/ home/user/public_html」が返され、「index.php」ファイルでdirname( __FILE__ )を呼び出すのと同じです。相対パスは同じなので。

使用例:

_@include dirname( __FILE__ ) . '/your_include_directory/your_include_file.php';

@require dirname( __FILE__ ) . '/../your_include_directory/your_include_file.php';
_
5
aequalsb

別の可能性は、CLIバージョンが別のphp.iniファイルを使用していることです。 (デフォルトでは、php-cli.iniを使用し、標準のphp.iniにフォールバックします)

また、ライブラリのパスなどを設定するために.htaccessファイルを使用している場合、これは明らかにcli経由では機能しません。

3
John Parker

上記の承認された回答に加えて、次のものも使用できます。

chdir(__DIR__);
2
billynoah

Cronジョブを介して実行すると、PHPスクリプトはシェルから手動で開始した場合とは異なるコンテキストで実行される可能性があります。そのため、相対パスが正しいパスを指していません。

1
Jan Hančič

DIRは機能しますが、実際のサイトサーバーとはパスが異なるため、私のローカルホストでは機能しません。これを使って修正しました。

    if(__DIR__ != '/home/absolute/path/to/current/directory'){ // path for your live server
        require_once '/relative/path/to/file';
    }else{
        require_once '/absolute/path/to/file';
    }