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

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.

Related

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

Including file with backward slash is won't work in PHP?

Am running scripts using command-line .
Backward include path is doesn't work for me
eg: require("../../../../test.php");
(But in browser it works)
try
dirname(__FILE__); will give you real path to current directory and you're then about le to include your file
require(dirname(__FILE__)."/../../../../test.php");
From the command line, the base path should be the directory from which you are calling php. When running in the browser (through apache, etc) the calling path should be the webroot directory.
So you should specify the directory of the current script or call it from its own directory.
For instance:
require(__DIR__."../../../../test.php");
DIR is a PHP Magic Constant (http://php.net/manual/en/language.constants.predefined.php) which returns the directory of the currently running file.

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: 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.

Equivalent of running $_SERVER['DOCUMENT_ROOT'] when running php in terminal

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

Categories