crontabでPHPが動かない!require関連でハマったのでメモ。読み込み先ファイルのrequireにも注意!

これで久しぶりのドハマりをしてしまいました。

crontabでPHPを実行する際に、実行するPHPファイル内に外部ファイル読み込み(require_onceやinclude_onceなど)があり、それらが相対パスで指定されていると実行されません。

*/1 * * * * php /home/username/public_html/cron/cron.php

cron.phpファイル内

//これでは動かない
require_once('sample.php');

これはcron自体はOS上のrootディレクトリにあるままで当該ファイルを実行するので、rootからの相対パスとなってしまうためパスが無効化されてしまうわけです。

この問題を解消するには、crontabで以下のように実行したいPHPファイルのあるディレクトリまで移動してから、PHPファイルを実行する方法があります。

*/1 * * * * cd /home/username/public_html/cron/ && /usr/bin/php /home/username/public_html/cron/cron.php

URLでアクセス可能な位置にPHPファイルが配置されているのであれば、curlやwgetを使って当該URLにアクセスさせることでPHPファイルを実行させるという方法もあります。

しかし、URLでアクセスできない&アクセス制限的なことがあると厄介になります。
その場合は単純にPHPファイル内の外部ファイル読み込み箇所の相対パスを絶対パスに置き換える以下の方法があります。

$path = realpath(dirname(__FILE__));
require_once( $path. '/../../sample.php');

しかし、実はこの方法にこそ隠れた大きな落とし穴があるのです。
実はこの方法、読み込み先のsample.php内が仮に以下のような感じになっていた場合はそこも相対パスから絶対パスに変更しなければなりません。

sample.php内

//相対パスだと動かない
require_once('config.php');

//絶対パスに変更
$path = realpath(dirname(__FILE__));
require_once( $path. '/config.php');

つまり、このcronジョブに関するすべてのPHPファイルの外部読み込み箇所をすべて「絶対パス」に変更しなくてはならないのです。
cronで実行するPHPファイル内だけでなく関連ファイルすべてなので見落としがちなのです。


気がつけば1分、気がつかなければ数時間〜数十時間、このてのドハマりの悲しいところです。