PHP: Require path does not work for cron job? - php

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.

Related

crontab cannot read dir '../' in php script

Why can't crontab read the '../' dir in the script, but if I access the script through a browser it can and there are no problems.
example: file.php
<?php
include('../config.php');
?>
If I run the script through the terminal config.php it can't be read '/usr/bin/php /home/example.com/public_html/cron/file.php',
whereas if I open it through a browser it runs smoothly
https://example.com/cron/file.php
I use php7.4 and os centos7
This is a perfect use case for why you should avoid using relative paths and instead stick to using absolute paths when including other scripts/files. PHP resolves relative paths according to the CWD (Current Working Directory) which will be different between your web server and your terminal. For the web server it depends on which script invoked the interpreter (in your case this is /home/example.com/public_html/cron/file.php). In the terminal it depends on from which directory the interpreter is loaded in the shell. In the case of a crontab it is the $PWD variable set in the home directory of the user that owns the crontab (so most likely /home/{username}). Of course that those two resolve to completely different paths.
So instead of all this guess work and instead of trying to change the CWD adhoc (which involves further guess work), you could simply use an absolute path at all times.
<?php
include __DIR__ . '/../config.php';
What this allows you to do is set the absolute path to the magic __DIR__ constant, which is a compile-time constant set to the path of the script in which it is used (in your case this is /home/example.com/public_html/cron). Then you can relatively go down one directory from that absolute path in order to get to /home/example.com/public_html from which you can now safely access config.php regardless of how you invoke the script and the given CWD.
.. references the parent directory of wherever the script is executing. It's presumably different in the two scenarios. Try cd /home/example.com/public_html/cron && /usr/bin/php file.php in your crontab, so that you're executing that in the same directory as your web page is.

What is the best practice to include files in PHP?

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.

PHP include in a cron job

I'm trying to setup a PHP file as a cron job, where that PHP file includes other PHP files.
The file itself is located at /var/www/vhosts/domain.com/httpdocs/app/protected/classes/cron/runner.php
The include file is at
/var/www/vhosts/domain.com/httpdocs/app/protected/config.php
How do I include that config file from runner.php? I tried doing require_once('../../config.php') but it said the file didn't exist.. I presume the cron runs PHP from a different location or something.
The cron job is the following..
/usr/bin/php -q /var/www/vhosts/domain.com/httpdocs/app/protected/classes/cron/runner.php
Any thoughts?
Your cron should change the working directory before running PHP:
cd /var/www/vhosts/domain.com/httpdocs/app/protected/classes/cron/ && /usr/bin/php -q runner.php
Note that if the directory does not exist, PHP will not run runner.php.
You should use an absolute path. The cron is probably not running the script from within the directory in which it resides.
I recommend using:
require_once( dirname(__FILE__) '../../config.php )
__FILE__ is a special constant that refers to the file you're in. dirname(...) will give you the directory, which will evaluate to the absolute path of the file you wish to include.
Is classes or cron a symbolic link? I seem to remember that php evaluates the real path instead of the symbolic path.
Consider the following directory tree:
/target/index.php
/path/sym -> /target
if you were to execute php index.php from /path/sym then the statement require_once('../require.php'); would evaluate to require_once('/require.php'); not require_once('/path/require.php');
You can change the working directory inside your PHP script to the location of that script:
chdir(__DIR__);
(or, if your PHP version is before 5.3: chdir(dirname(__FILE__));)
Then you can do:
require_once('../../config.php')

PHP Cron Job: Including file not working?

i run a cron job every night, but for some reason, it is saying that the file i try to include is inexistant:
Warning: require(../includes/common.php): failed to open stream: No such file or directory in /home/fini7463/public_html/cron/journeyNotifications.php on line 2
Fatal error: require(): Failed opening required '../includes/common.php' (include_path='.:/usr/lib/php:/usr/local/lib/php') in /home/fini7463/public_html/cron/journeyNotifications.php on line 2
here's the code:
set_include_path('/home/fini7463/public_html/includes/');
require 'common.php';
the file 'common.php' is located as follows
public_html => cron => journeyNotifications.php
=> includes => common.php
i even set the include path (as shown in the code), but i am still getting this error. what could the problem be?
thanks!
If you do require('../includes/common.php'), the path is traversed relative to the current working directory.
If you do require('common.php'), the file is searched in the include path, and in the directory of the script which calls the require().
To solve this, first change directory in your crontab:
cd /home/fini7463/public_html; php -f cronjob.php
Calling set_include_path() as you do trashes the previous path. The call replaces the previous path with whatever you're passing as an argument, so if any of your code loads other libraries (ie: PEAR/PECL modules), they'll no longer be accessible as you've trashed the include path. You should use:
set_include_path(get_include_path() . PATH_SEPARATOR . '/home/fini7463/public_html/includes/');
That will append your new path to the include path.
As well, you can never quite tell what the working directory will be when cron fires up your script. It could be the home directory of the user you're running the script as, could be /tmp, or some other directory entirely. If you want to use relative paths in the script for anything, you'll have to make sure the working directory is set to a known value. Either by using a 'cd' in the crontab, or using a 'chdir' inside the script before doing anything involving the relative paths.

include path and cron

I'm running a cronjob that calls a php script. I get "failed to open stream" when the file is invoked by cron. When I cd to the directory and run the file from that location, all is well. Basically, the include_once() file that I want to include is two directories up from where the php script resides.
Can someone please tell me how I can get this to work from a cronjob?
There are multiple ways to do this: You could cd into the directory in your cron script:
cd /path/to/your/dir && php file.php
Or point to the correct include file relative to the current script in PHP:
include dirname(__FILE__) . '/../../' . 'includedfile.php';
cron is notorious for starting with a minimal environment. Either:
have your script set up it's own environment;
have a special cron script which sets up the environment then calls your script; or
set up the environment within crontab itself.
An example of the last (which is what I tend to use if there's not too many things that need setting up) is:
0 5 * * * (export PATH = /mydir:$PATH ; myexecutable )
you need to see what is the path that the cron run from.
echo pathinfo($_SERVER["PATH_TRANSLATED"]);
according to this do the include
include $path_parts['dirname']."/myfile.php";

Categories