PHP include in a cron job - php

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')

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.

Run command in other folder

I have a php script that should run a command located in a certain subfolder, in another subfolder.
The command is in folder Cmd, and should be executed in folder 1.6.2. So first I switch to the 1.6.2 directory, and then I use a relative path to call the command:
exec("cd 1.6.2");
exec("..\Cmd\sencha app build production");
But this throws the error that the directory couldn't be found, because the second exec still executes in the main folder, where the calling index.php file resides.
The php manual on exec doesn't provide any possibility to execute in another directory. Am I missing something here?
The current system is a Windows, but I have to make it portable because it may be executed on linux in the future.
Try changing the working directory first
e.g.
chdir('/path/to/1.6.2');
exec("sencha app build production");
You have to change the directory within the same exec() command.
like so: exec("cd 1.6.2 && Cmd/sencha app build production"); depending on your actual folder structure. I'm just guessing)

Correct path to run python script with php from cgi-bin folder

I want to run python script 'test.py' from my cgi-bin directory on my webserver. the cgi-bin directory is at 'www/cgi-bin/'. The python scrip is in that directory. The php code I'm executing is at 'www/html/website/index.php'.
what is the correct path that goes here ------> exec('path');
TYVM
edit:
My python script has been chmod +x'd and is executable (I have tested)
Assuming the PHP script is in the same directory as the "www" directory.
<?
exec('./www/cgi-bin/test.py');
?>
or without chmoding, you can run it through Python
<?
exec('python ./www/cgi-bin/test.py');
?>
Your PHP code is executing in the www/html/website/ directory then. You need to go up two directories (arriving in the www/ directory), then go down to the cgi-bin/ subdirectory. So this should work:
exec('../../cgi-bin/test.py');
Note that this is relying on the current work directory being the PHP script directory. This might not always be the case, particularly if something in the PHP script changes the current work directory explicitly or simply if this PHP script is included from a different script. So it is better to use absolute paths (e.g. put the absolute path of the base directory into a config file).

PHP: Require path does not work for cron job?

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.

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