Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Schedule scripts without using CRON

I know there are many posts about using CRON to run a php file. But, in the world of shared hosting, and ease of setup for a user, I don't want to have to mess with that.

I found another solution online that has to do with sockets. Just wanted to get everyones take on this, and tell me if this is a good or bad idea. Sounds like it works well.

Thoughts?

//Open socket connection to cron.php
$socketcon = fsockopen($_SERVER['HTTP_HOST'],80,$errorno,$errorstr,10);
if($socketcon) {
$socketdata = "GET /cron.php HTTP 1.1\r\nHost: ".$_SERVER['HTTP_HOST']."\r\nConnection: Close\r\n\r\n";
fwrite($socketcon,$socketdata);
//Normally you would get all the data back with fgets and wait until $socketcon reaches feof.
//In this case, we just do this:
fclose($socketcon);
} else {
//something went wrong. Put your error handler here.
}

cron.php:

//This script does all the work.
sleep(200);
//To prove that this works we will create an empty file here, after the sleep is done.
//Make sure that the webserver can write in the directory you're testing this file in.
$handle = fopen('test.txt','w');
fclose($handle);

Found the script from a blog post: http://syn.ac/tech/13/creating-php-cronjobs-without-cron-and-php-cli/

like image 800
Nic Hubbard Avatar asked Jan 27 '10 00:01

Nic Hubbard


3 Answers

It's not a bad method, but you need to ensure that by closing the socket it isn't just terminating the script before it finishes. You can set sockets to non-blocking.

I would still use a cron job, even if it is a bit of a pain.

like image 50
Xorlev Avatar answered Oct 23 '22 12:10

Xorlev


A cron job basically is a cron job. you set it up, and the OS runs the job for you. I am not sure how the PHP script you got from the site works, but if it requires human intervention, then its not really called a cron job. If you don't want to use cron, you can use a loop, then use the date functions of PHP to set up a date and time. Pseudocode

while (1) {
    $d=date("d");
    if ( $d == "01" ){
        //run every 1st of month
        //code to run here
    }
}
like image 4
ghostdog74 Avatar answered Oct 23 '22 11:10

ghostdog74


This produces a different effect than cron.

A cron job runs during certain times which you have set ahead of time.

Your method basically is a kind of "fork" or "asynchronous call" to a PHP script. Doing it via HTTP like you are doing here is a cheap and easy technique. I use it myself. It's different from cron in that it launches the "background process" immediately.

A few comments, though:

  1. First of all, you should be calling ignore_user_abort() in the "background" script. Otherwise, in many environments your script will be aborted when the "calling" script closes the socket.

  2. Secondly, you can actually check the $_SERVER['HOST'] variable in the "background" script, and in this way you can have scripts which are not exposed to the internet (basically issue requests to localhost and check for that in the background script). You can then presumably trust requests coming from your own machine, and skip all the security checks, sessions, and so forth.

  3. Thirdly, who says that the "background" script has to be run with PHP? PHP has a lot of weaknesses if you are going to use it as a "background" process. The main weakness is that it blocks on I/O. So if you are going to be sending emails, updating database rows, or whatever, you are basically pausing your script every time you send a request. Whereas with Node.js, for example, you can fire off I/O commands asynchronously and keep going. If you're going to use PHP, at least make sure to send 10 emails at a time, or update 10 rows at a time, or something.

  4. Finally, you might want to display a progress bar on the browser if a background script is doing something. So you're going to need to use a common data store (like your database) to record the progress for the task.

like image 2
Gregory Magarshak Avatar answered Oct 23 '22 10:10

Gregory Magarshak