I have a CRON job php script that I just set up not too long ago. However, I noticed that the PHP file executed (without the cron job activating). It appears that it happened when a Google Bot crawled the file, because I noticed that the following engine visited my page:
http://www.google.com/bot.html
My question is:
1) Is it possible, that by crawling my webpage, it could have executed the script?
2) How can I "hide" the CRON file from Google?
3) Would it be smart to place this file in somewhere other than my public_html directory?
Many thanks!
1) of course it is
2) see robots.txt (http://www.searchtools.com/robots/robots-txt.html)
3) yes. but if for some reason you depend on calling it via a http daemon you can use a little trick.
eg. first line of code:
if(!isset($_GET['execute'])
exit;
in your crontab:
http://server.tld/file.php?execute=1
1) If the file is placed in a public web directory, then yes, it could be executed by Googlebot (or any other visitor)
2) You could add a Disallow clause for it in your robots.txt. Any regular user can still go and execute it by visiting if you do this.
3) Yes.
You can use also php-cli. Define if it is cron job:
define('_DOING_CRON_', true);
Then in php file:
if(_DOING_CRON_ && php_sapi_name() != 'cli'){
die("You cannot get here: this is only cron task.");
}
Runifus' answer above solved it for me, however the Cron job command line does not work with the ? in the url to pass the querystring as I learnt here: Cron Jobs calling a PHP script with variables
It should be like so:
http://server.tld/file.php execute=1
also the php condition is missing a closing parenthesis
if(!isset($_GET['execute'])) exit;
Related
Is there a way to call a script from a cron job only and make it so no other ips can run that script?
I have a script that sends notifications to phones. It is supposed to be called by a cron job once day, but sometimes something triggers it and everyone gets notified when they shouldn't. I would like to limit it to be called from my server only.
In other words to make it not to be able to be called from a browser or a spider etc..
Thanks
I'd suggest that you don't make this file available publicly.
But to answer your question directly; A way to do this is to add the following check:
if (php_sapi_name() === 'cli') {...}
More info: https://secure.php.net/manual/en/function.php-sapi-name.php
Your script seems to be available via public URL. Move it somewhere else. For example, if the script is within /www/site.com/public/script.php, and /www/site.com/public is the public directory of the Web server, move it to some /www/site.com/cron/script.php. Make sure that the Web server is not configured to fetch files from the cron directory.
As others have written, there may be other setups you could use, (permissions and file locations) however, I've never been someone who tells someone to re-engineer their whole process to meet a single need. That feels too much like the tail wagging the dog. Therefore, if you wish to have a script that can only be executed by your cron job and not mistakenly by another process, I would offer you this solution
The php_sapi solution has been noted to provide inconsistent behavior and is system configuration specific (for example echo it's output when calling your script from the command line, and again when calling from a cron). This can lead to tracking down other bugs. The best solution I have seen and used, is to pass a command line argument to your script and evaluate the existence of that argument.
your cron job would look something like:
* * * * * * php /path/to/script --cron
Then, inside your script you would perform an if check, that when not satisfied, stops the script.
if( $argv[0] != 'cron')
{
//NO CRON ARGUMENT SUPPLIED, SOMETHING ELSE MUST BE CALLING THIS
exit;
}
Take not that some systems may use the first argument as the script name, so based on your individual system configuration, you may need to check $argv[1]
Hope this helps, let me know if you have any questions, I'm happy to respond or edit if needed.
I want every day to check my database and do some staff with it. Cronjob is amazing solution. But how to make authentification? Otherwise anyone can trigger that code at any time. Thank you.
For example usually person must insert login and password, get token and store it in cookies. After that you have rights to change anything. How to make it in cronjob.
add cron job in is such way so that php file run from CLI.Don't run it by sending http request.Command for running as CLI will be like php test.php
and add the following code in the php file so that it is only allowed to run from CLI:
if (php_sapi_name() == "cli") die('run only from CLI');
This could be a kind of strange question. I have a php file in a public web site where I have access to the server. For the moment we do not need to set Cron job for this file execution. However I need to limit the execution of this file only via localhost. I don't have any precise idea about the way should I do this. Is there any way to detect whether the request is localhost or not? I mean with PHP. Or should I need to handle this via security setting or firewall of the server?
I'm assuming you mean you want to be able to execute the script only from the server, and not via the web from another host. You have two options:
Option 1
move it out of the public_html folder. There is no reason you should not take this option, unless there is something preventing you from doing so. In that case,
Option 2:
Wrap the entire code in the following if statement
if (php_sapi_name() == 'cli')
{
//your code
}
Alternatively,
if (php_sapi_name() != 'cli')
die();
//your code
This ensures your script will only run if invoked from the command line, and not via the web.
You could check IP addresses like this:
if($_SERVER["REMOTE_ADDR"]!=$_SERVER["SERVER_ADDR"])
{
exit;
}
I have set up a cronjob which updates a bunch of contracts in a certain system. When I run the PHP-script in a browser it all works fine, but when the cronjob has to do the trick it fails. I'm kinda stuck on this one since I don't have a lot of experience with cronjobs (heck.. I can only set them up in DirectAdmin).
My PHP scripts has some includes to some classes, these includes work properly (i've tested it by sending mails to myself line by line). When the base-classes are included I have a class which handles autoloading. When I do something like Class::GetInstance() it fails.
My cronjob looks like:
* * * * * /usr/local/bin/php /home/username/domains/domain/public_html/path/to/script.php
What can I do to fix this? Perhaps not run it via php, but by a browser or something? I'm sorry if this is a stupid question, but I don't know this ;)
Remeber that when PHP is executed on CLI with /usr/local/bin/php you do not have the $_SERVER variable setted properly! I had that problem too because my script had to use $_SERVER['DOCUMENT_ROOT']. As said, try to run it in a normal shell to see if it works. Alternatively you can change your cronjob command to:
wget -q http://yourdomain.com/path/to/script.php
Usually this works well because it is just identical to fetch that URL from a normal browser.
wget man page here: http://linux.die.net/man/1/wget
You can't always call the php file directly that expects to be called via HTTP. Judging from path, it's a part of website, which is normally executed by browser, hence I'ld set the cronjob up to not to be directly called by php-cli, but rather by doing a curl request to the website's URL.
"it fails" is not the problem description one can call a suffucient one.
add this line in your crontab file
MAILTO=your#mail
and run your jobs.
You will get the script output and be able either to correct your code or ask a sensible question.
You may also redirect stdout and stderr to a log file
I'm writing a PHP script that I want to disable from web access (I will ask users to move it out of the web root and execute via CLI, but you never know if they'll listen!)
Is there a simple function that occurs to anyone to make the page die if it's requested by a browser?
Thanks for any ideas.
You could test whether the script is being run through the CLI using php_sapi_name().
It can return a whole bunch of different possible values when run on a HTTP server - difficult to make a reliable distinction there - but there seems to be only one possible return value for the CLI: cli.
If you're looking for an all-purpose solution, make sure you read the comment thread below for more detailed discussion on some potential gotchas.
'PHP_SELF' The filename of the
currently executing script, relative
to the document root. For instance,
$_SERVER['PHP_SELF'] in a script at
the address
http://example.com/test.php/foo.bar
would be /test.php/foo.bar. The
FILE constant contains the full path and filename of the current (i.e.
included) file. If PHP is running as a
command-line processor this variable
contains the script name since PHP
4.3.0. Previously it was not available.
http://www.php.net/manual/en/reserved.variables.server.php
I'm not a PHP expert but you could check the $_SERVER variable ?
You can use php-sapi-name function to detect if script was requested by web server or cli interface.
$sapi_type = php_sapi_name();
if (substr($sapi_type, 0, 3) != 'cli') {
die "You are not using CLI".PHP_EOL;
}
you can use php-sapi-name or you can use the predefined constant which is marginally faster (although you'd never notice!)
<?php
if(PHP_SAPI != 'cli') exit;
// continue