Относительный путь, не работающий в скрипте PHP cron

Если PHP-скрипт запускается как cron-скрипт, включенные функции часто терпят неудачу, если используются относительные пути. Например, если у вас есть

require_once('foo.php'); 

файл foo.php будет найден при запуске в командной строке, но не при запуске из cron-скрипта.

Типичным обходным путем для этого является первый chdir для рабочего каталога или использование абсолютных путей. Я хотел бы знать, однако, что отличается между cron и shell, что вызывает это поведение. Почему это происходит при использовании относительных путей в скрипте cron?

Измените рабочий каталог на текущий путь к файлу. Просто используйте

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

в рабочем файле. Тогда вам не нужно будет изменять все относительные пути к абсолютным путям на каждой странице.

Рабочий каталог сценария может отличаться при запуске из 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 

Единственный шанс, который я получил «require_once» для работы с cron и apache в то же время, был

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

Другая возможность заключается в том, что версия CLI использует другой файл php.ini. (По умолчанию он будет использовать php-cli.ini и вернуться к стандартному php.ini)

Кроме того, если вы используете файлы .htaccess для установки пути к библиотеке и т. Д., Это явно не будет работать через cli.

Потому что «текущий рабочий каталог» для заданий 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».

Если вы вызываете dirname( __FILE__ ) в «your_php_file.php», вы получите «/ home / user / public_html / your_directory», даже если активный скрипт находится в «/ home / user / public_html» (обратите внимание на отсутствие завершающей косой черты ).

Если вам нужен каталог INCLUDING-файла, используйте: dirname( $_SERVER['PHP_SELF'] ) который будет возвращать «/ home / user / public_html» и совпадает с вызовом dirname( __FILE__ ) в файле «index.php» так как относительные пути одинаковы.

пример использования:

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

В дополнение к принятому ответу выше, вы также можете использовать:

 chdir(__DIR__); 

При выполнении задания cron ваш PHP-скрипт, вероятно, работает в другом контексте, чем если вы его запускаете вручную из оболочки. Поэтому ваши относительные пути не указывают на правильный путь.

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'; }