I just faced that code
include('../wp-load.php');
Worked just if script called from web-browser (equals to 'from Apache'). If I'm running the same script from cron or from command line I receiving error
Warning: include(): Failed opening '../wp-load.php' for inclusion (include_path='.:/usr/local/php54/pear') in /home/myfolder/public_html/exe/myscript.php on line 6
However it worked if I modify the include in the following way:
include(__DIR__.'/../wp-load.php');
It works from both: command line and from browser.
In the same time I begun to be scared to use includes from the directory where the script placed. So if tools.php placed in the same directory is it safe to use:
include('tools.php');
Or it would be better to add __DIR__?
include(__DIR__.'/tools.php');
At the top of the script, or in the file that you always include at the beginning, define constant or variable that is the path to your directory root.
You should define two paths:
one from your machine, for example:
define('SERVER_PATH', '/var/www/');
this will be used for including php script files in your php script
You will just use it like include(SERVER_PATH.'tools.php') anywhere in your code.
You can also use __DIR__ instead, if you have PHP >= 5.3.0
And second - url path:
define('URL_PATH', 'http://www.xxxxxx.com/');
this will be used for things by your page for http requests like images, javascript files, css files etc.
Cron has its own working directory, but you can change it with cd:
cd /var/www/vhosts/domain.com/httpdocs
You also need to know you can execute multiple commands in cron job like this:
command1 && command2
So command1 can be the cd and command2 your php.
Then you don't have to add __DIR__ and a cron job will work just like normal PHP.
I know this doesn't really answer your question, but it does solve the problem that made you ask your question. Personally I don't think there's a good reason to always use absolute paths in the includes, relative paths will do just fine in most cases.
Related
test3.php
<?php
require("../includes/config.php.inc");
echo "done";
?>
Works fine when I launch it in my web browser (it says done), but when I use
/usr/local/bin/php -f /home3/site/public_html/order/functions/test3.php to run the same file as a Cpanel cron job, I get an email saying there was an error.
Warning: require(../includes/config.php.inc): failed to open stream: No such file or directory in /home3/site/public_html/order/functions/cron_renewal.php on line 1
The difference lies in the current directory is different when the script is run from browser or from cron. Try using dirname(__FILE__) or __DIR__ instead. For example, try:
<?php
require(__DIR__ . "/../includes/config.php.inc");
echo "done";
?>
In my opinion this is the most flexible way, since you don't have to make your cron command to complicated (you just run the script) and you can move the sources along the harddrive and you don't have to hardcode any paths.
edit: the same approach applies to other platforms, such as python, ruby, etc. ;) this is just a "good practice" ;)
Maybe this way?
cd /home3/site/public_html/order/functions/;/usr/local/bin/php -f test3.php
The includes are relative to the current working directory.
(Maybe this is not the correct directory... You should cd to the file's parent directory which is working from web.)
I have a cron job that needs to include this file:
require '../includes/common.php';
however, when it is run via the cron job (and not my local testing), the relative path does not work.
the cron job runs the following file (on the live server):
/home/username123/public_html/cron/mycronjob.php
and here's the error:
Fatal error: require(): Failed opening required '../includes/common.php'
(include_path='.:/usr/lib/php:/usr/local/lib/php') in
/home/username123/public_html/cron/mycronjob.php on line 2
using the same absolute format as the cron job, common.php would be located at
/home/username123/public_html/includes/common.php
does that mean i have to replace my line 2 with:
require '/home/username123/public_html/includes/common.php';
?
thanks!
With all do respect to all the current answers, they all went to "change the php code" approach.
I don't like to change my PHP files just to run it from a cron because it reduces the code portability and increases the chances to forget to change one or two relative paths and break the program.
Instead change the directory at the cron tab line, and leave all your relative paths and your PHP files untouched. For example
1 1 * * * cd /home/username/public_html/&& php -f script.php
check this answer
also check this article, I will quote the relative part
Depending on the code in your PHP script, it may only run correctly when called from a specific directory. For example, if the script uses relative paths to include files, it will only run if it is called from the correct directory. The following command shows how to call a PHP script from a specific directory:
cd /home/username/public_html/; php -q script.php
Technically seen the php script is run where cron is located; ex. If cron was in /bin/cron, then this statement would look for common.php in /bin/includes/common.php.
So yeah, you'll probably have to use fullpaths or use set_include_path
set_include_path('/home/username123/public_html/includes/');
require 'common.php';
nono. you need to use absolute paths on crons.
what I do is:
// supouse your cron is on app/cron and your lib is on app/lib
$base = dirname(dirname(__FILE__)); // now $base contains "app"
include_once $base . '/lib/db.inc';
// move on
An alternative to the solutions which recommend absolute path specification is using a chdir in your script. That way, your relative paths will work as expected.
For example, to change to the directory of the script:
$curr_dir = dirname(__FILE__);
chdir($curr_dir);
To change to the parent directory of the script:
$curr_dir = dirname(__FILE__);
chdir($curr_dir . "/..");
And so forth.
If the relative path doesn't work, then it means that the current directory set when the cron tasks are running is not /home/username123/public_html. In such cases, you can only use an absolute path.
It sounds as simple as just some script you are running is setting the include_path and you are including that script. use phpinfo() to check the include_path global vs local setting.
I was wondering if there is some variable that will return what $_SERVER['DOCUMENT_ROOT'] returns when I call PHP like this: ./somescript
If not, how do people get around this case? I'm looking to be able to call the same script (a template compiler) in both the web browser and the terminal.
Thanks!
Matt Mueller
I don't recommend the getcwd() command for this because you cannot be sure of where cwd is pointing unless you've made a chdir before (which mean you already know which directory you're in). Working directory can be define in php config and vary between apache and CLI, and some php frameworks changes it on startup.
Use dirname(__FILE__) it always works wether you're in a apache or cli context (plus it works on windows and unix), and if you need to move inside your project files you can just use relative paths.
I think you should use getcwd function to obtain current directory (or just dirname(__FILE__) if your script is the top one). Then you only need to be sure to run the script from your DOCUMENT_ROOT. Something like this:
cd /var/www/
php ./scripts/top.php
hardcode document root in it.
hardcode is always a solution
I'm using $_SERVER['DOCUMENT_ROOT'] for my include paths so files will figure out where they are running from (i.e. whether they're on live or staging) and it works fine, except for scripts that are run by cron in which I have to hardcode the path.
Is there another variable I could use that could work from both cron and the browser?
When running your PHP script through cron, I assume it is executed in the context of the CLI instead of the web server. In the case of executing PHP from the CLI, the $_SERVER['DOCUMENT_ROOT'] is not populated correctly. You can use the following code to work around this:
if ($_SERVER['DOCUMENT_ROOT'] == "")
$_SERVER['DOCUMENT_ROOT'] = dirname(__FILE__);
The following will give you the directory that your script is located in:
realpath(dirname(__FILE__));
This works for both web requests and cron scripts.
The best thing to do is to define your own constant that you can reference from anywhere else in your app. For example, you can put something like this in MyAppDirectory/public_html/index.php:
define('APPLICATION_PATH', realpath(dirname(__FILE__).'/..'));
This will give you a consistent reference back to MyAppDirectory/ regardless of where index.php is called or included from. Defining your own constant not only allows you to call your application from cron or through the browser like you want, but will also allow you to change your storage structure in much larger ways with minimum changes to track down. Zend Framework uses this heavily with its Zend_Application bootstrap process, and googling for "php APPLICATION_PATH" will provide you with a variety of further references.
You can use chdir() function, if your script is running via cron:
chdir(dirname(__FILE__)); //avoid conflict with "cron path" and app base path (if script runs via 'Cron')
I work on Windows, so use "nnCron", but it have to work on Linux too.
When calling php via cli, the current directory is NOT changed to the one of the script. All the scripts i have running in crontab run via the CLI, so this is an issue.
I'm currently fixing the problem by doing a chdir() with the absolute path where the script is, but i REALLY dont like hardcoding paths into stuff like that.
I'm looking for the most portable/reliable method for ensuring that the current working directory is the one where the script it is at.
chdir(dirname(__FILE__));
You can use __FILE__ to get the full absolute path to the executing file itself:
<?php
echo "I'm here: ".__FILE__."\n";
?>
See the documentation for more info.