Относительный путь не работает в cron PHP скрипт
Если PHP script запущен как cron script, то часто включает ошибки, если используются относительные пути. Например, если у вас есть
require_once('foo.php');
файл foo.php будет найден при запуске в командной строке, но не при запуске cron script.
Типичным обходным решением для этого является первый chdir для рабочего каталога или использование абсолютных путей. Я хотел бы знать, однако, что отличается между cron и shell, что вызывает это поведение. Почему это происходит при использовании относительных путей в cron script?
Ответы
Ответ 1
Рабочий каталог script может быть другим при запуске из cron. Кроме того, была некоторая путаница в PHPs 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
Ответ 2
Измените рабочий каталог на текущий путь к файлу. Просто используйте
chdir(dirname(__FILE__));
include_once '../your_file_name.php'; //we can use relative path after changing directory
в текущем файле. Тогда вам не нужно будет изменять все относительные пути к абсолютным путям на каждой странице.
Ответ 3
Единственный шанс, что я получил "require_once" для работы с cron и apache в то же время, был
require_once(dirname(__FILE__) . '/../setup.php');
Ответ 4
Другая возможность заключается в том, что версия CLI использует другой файл php.ini. (По умолчанию он будет использовать php-cli.ini и вернуться к стандартным php.ini)
Кроме того, если вы используете файлы .htaccess для установки пути к библиотеке и т.д., это явно не будет работать через cli.
Ответ 5
Поскольку "текущий рабочий каталог" для заданий 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", даже если активный script находится в "/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';
Ответ 6
В дополнение к принятому ответу выше вы также можете использовать:
chdir(__DIR__);
Ответ 7
При выполнении задания cron ваш PHP script, вероятно, работает в другом контексте, чем при запуске вручную из оболочки. Поэтому ваши относительные пути не указывают на правильный путь.
Ответ 8
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';
}