1

I want to run a PHP script in the background using another PHP script.

I had this in mind:

exec('/usr/bin/php background.php &');

My webhost has only disabled access to exec().

The only other way I can think of is sending a mail() to an email forwarder which is piped to a script, but that's rather a wacky workaround than a solution.

Does anyone know any solution?

3
  • have you tried system() or shell_exec() ? Commented Feb 24, 2012 at 13:32
  • Yes, they're also disabled. And backticks too. Commented Feb 24, 2012 at 13:36
  • I can't see any solution to do a background process Commented Feb 24, 2012 at 13:38

2 Answers 2

5

You could achieve that by using curl and loading the script as a web resource so it can be executed. If that script needs to be protected from public, you can check if the request came from the same server:

if( $_SERVER['SERVER_NAME'] != 'localhost' 
        || $_SERVER['REMOTE_ADDR'] != '127.0.0.1'
        || stripos( $_SERVER['HTTP_USER_AGENT'], 'wget' )===false
        )
{
    // Access Denied!!
    die();
}

Be sure to make an asynchronous request with curl, so if the script takes a lot of time to execute, doesn't hang the original user request (use curl_setopt( $handle, CURLOPT_HEADER, false );

So the plan is from the page where you know you need to execute the script, launch an Http request to the script (this is a very basic example of using curl library):

$handle = curl_init();
curl_setopt( $handle, CURLOPT_URL, 'http://localhost/your_script.php');
curl_setopt( $handle, CURLOPT_HEADER, false );
curl_exec( $handle );
curl_close( $handle );

Then in your script, use the above script to protect requests not comming from current server, and do the job.

Updated
As stated in this question: sending a non-blocking HTTP POST request In your script job you could send this header to close the connection as script is running:

// Send the response to the client
header('Connection: Close');
// Do the background job: just don't output anything!

Updated II
Reviewing my own answer, I've checked that curl_setopt( $handle, CURLOPT_HEADER, false ); does not create an asynchronous request. I still have not found how to do it.

Sign up to request clarification or add additional context in comments.

6 Comments

Thank you for your nice answer! Only, it still keeps waiting for the background process to finish. Is there any way I could set something like a timeout of 0 seconds in cURL?
Ah, got it! curl_setopt( $handle, CURLOPT_TIMEOUT, 1); It does generate a race condition however; If it takes longer than 1 second to connect this won't work. Also. it keeps the user waiting for one extra second, but I guess I'll just have to accept that.
You'll need to develop a way that will block second visitor for running the background request if the job is still working.
I've updated my answer with a possible way to close connection once script is reached.
Thank you sir clinisbut. This is exactly what I was looking for!
|
1

I haven't tested this, but if you are able to use curl, you could possibly create background.php with ignore_user_abort() and curl it from your main script with a low timeout. The script the user sees will be delayed slightly because it has to wait for the curl request to timeout, but your background should continue working.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.