I know this question has been asked before, but none of the answers are working for me.
I'm trying to run a simple PHP script every night at midnight. I created a file called "autoDelete.php" that contains just this code:
<?php
include 'my-database-connection.php';
mysql_query("DELETE FROM meetings WHERE indexDate < NOW()");
?>
I know this script is working because if I navigate to it in a browser, it does what it should.
I then set up the Cron job (via GoDaddy cPanel) to run every minute, with a command to run the script using this:
* * * * /usr/bin/php -q /home/username/public_html/autoDelete.php
However, this is not working. I suspect this has something to do with whatever precedes the "/home" in the command.
Some things to check:
1) cron jobs' default "working directory" is the home directory of the user ID they're running under. That'd most likely be /home/username in this case. That means if you have any relative-pathed include/require commands, they're going to be relative to /home/username, NOT /home/username/public_html. Make SURE that all necessary files are accessible.
2) You're simply assuming the query call succeeded. That's exactly the wrong the thing to do. Calls to external resources (DBs in particular) have exactly ONE way to succeed, and a near infinite number of ways to fail. ALWAYS check for failure, and treat success as a pleasant surprise.
Combining these two (failing to include your connection script, and failing to check for failure), and you end up with what you've got: "nothing" happening. At least try something like
mysql_query(...) or die(mysql_error());
^^^^^^^^^^^^^^^^^^^^^^
The error message will become your script's output, and get emailed to the controlling account's mailbox.
I've had issues in the past with running PHP scripts in a cron job when trying to invoke the PHP binary directly. My solution was to use wget in the cron job since the script was servable by Apache anyway (0 0 * * * wget url/of/script.php). Apache already has the right PHP environment set up so might as well just ask it to handle the job.
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.
today i learned about cron jobs, i opened SSH and followed along with the 1and1 cron job tutorial, the tutorial file and instructions worked fine however when i did the same steps but with my own PHP script it didnt work, below is the cron job command i used
* * * * * /usr/bin/php /path-to-webspace/heal.php
and below is the heal.php file, this file works as intented without cron as i tested it beforehand
<?php
include('onedirectorydown/database_connection.php');
$resetAllHealth = "UPDATE users SET Health = Health + 1000";
$executeAH = mysqli_query($dbc, $resetAllHealth);
?>
i want it to execute every minute as im just testing it to see if it works but it doesnt, however the sample in the 1and1 tutorial worked and i basically followed along exactly, i just the file contents to whats in the heal.php
could someone tell me why it is not executing?
Common issues with CRON jobs are that required include files aren't working properly. For example:
include '/database.php';
Might try to include /var/www/database.php when executed from the browser, but might try to include /home/username/database.php when executed from the CRON job of the appropriate user.
Consider replacing calls with
include $_SERVER['DOCUMENT_ROOT'].'/database.php';
and seeing if that helps.
Looking at your last comment, maybe you don't have the right mysqli extension installed into the php.ini file for cli (usually under /etc/php5/php.ini).
Remember: "apache" scripts and "command line" scripts have two different php.ini files.
I wanted to implement two cronjobs with different execution time. One cron job is for sending emails and second cron job for validating my application subscriptions.
I write one crontab file and write to two cronjob as follows:
2 * * * * path to mailCronjob mail.php
20 * * * * path to check my application's subscriptions sub.php
The problem is first cronjob is working fine. Mail will delivers fine, but the second cronjob
is not working. I tried to run second job manually, its also working fine.
I am using command to set cronjob as:
crontab crontab_file
when I give command crontab -l
it also shows both cronjob in command line.
I wanted to ask, am I missing something here, or what should I do to run those cronjobs.
FACT: you can run as many cron jobs from a single crontab file as you wish.
FACT: you can also run different jobs as different users, each with their own crontab file.
SUGGESTION:
1) Just debug what's wrong with your second job.
2) It could be path, it could be permissions; it's more than likely environment (the environment for "cron" can be different from the environment for the same user from a command line).
PS:
Try this, too:
How to simulate the environment cron executes a script with?
Debugging crontab jobs
Check the owning user's email and see if an error report has been sent to it.
If you need to be a certain user and have that user's environment change your call to
su - -c "/path/to/sub.php" SubScriptUser
If your script only works from a certain directory use
cd /path/to/ && ./sub.php
I recall the same problem. For some reason, I had to press enter after my second cron job. Even in the first cron job, if it is the only job, needs a CR/LF (enter). Cursor needs to be on second line (if there is one cron job)... cursor needs to be on the third line, if there is two cron jobs. I guess, needs to read the file completely to interpret the cron job command. I just share this, because if you dont do that, only the first job will be executed, and skips the second one totally unless enter is pressed at the end of the second job. Best regards and cheers... Test that and let us know.
You need to add an empty line to the end of the config file
I never did 2 actuall cronjobs in one cron-tab file, but rather had the one cronjob execute every 15 minutes and query the database or look into a config file what tasks are there to execute, maybe this concept helps you.
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 have a CakePHP script that should hopefully be run by a cron job. It runs fine from the command line, but seemingly not from the cron. The cron line is something like:
*/2 * * * * cd /path/to/app;../cake/console/cake do_update
The script itself - and this is the bit that I think may possibly be too wacky, to the extent of throwing off the cron - loops through a subset of a Realtors table in the database, using the system time to decide which 50-record slice of the database to update:
$realtors = $this->Realtor->find('all',array(
'conditions'=>array('Realtor.zone_id'=>1),
'order'=>array('Realtor.num DESC'),
'limit'=>50,
'offset'=>date("i")*25
));
So my question(s) is/are - is there anything I'm doing here that would obviously throw the cron job for a loop? And, perhaps more importantly, is my method of splitting a database into manageable chunks over the course of an hour crazy? (I'm pretty much a programming newbie, so I try a lot of things without knowing whether they're good practice or not.) Can anyone suggest a better way of looping through and updating large numbers of database records via a cron, that prevents the individual queries from being too huge for the system to handle?
EDIT: not only does it always work from the command line, it also works when run by cron script on a different server. I guess there's just something messed up on the particular server, so it seems doubtful there's a code-related solution! I'll just accept an answer from among the useful cron-related insights below...
Generally, you'd want to put all your command line stuff into an shell file
/path/to/cake/console/cron.sh
#!/bin/sh
cd /path/to/app
php ../cake/console/cake do_update
*/2 * * * * sh /path/to/cake/cron.sh
Normally I don't care about where the application actually starts (if i'm not using files) and just do
*/1 * * * * php /my/path/my_php.php
I'd try to put "cd /path/to/app;../cake/console/cake do_update" in bash script and run the script in cron instead. But I'm not sure if it'll help.
Try following the manual, it's working great for me:
http://book.cakephp.org/view/1110/Running-Shells-as-cronjobs
I'm not that familiar with cron, but I didn't think you could run two commands together like that.
You might want to try:
*/2 * * * * cd /path/to/app && ../cake/console/cake do_update
This will cause the two commands to run together (since each command does return a number to indicate success or failure, and in the event of failure, an error code)
I am assuming your PHP file also includes the necessary #! line at the start pointing to the PHP interpreter, and that the file permissions allow for execution from the command line? (i.e. you can just literally run that statement above and it works)