Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 649
  • Last Modified:

PHP Start Background Scripts in either Linux or Windows without waiting for completion

How do I start a PHP script to run in the background so my foreground process in a web browser doesn't freeze waiting for it to end.

Secnario:
User uploads a file
After saving the file, I kick off a background PHP script to process it
When the background script ends, it sends the user an email to notify them.

I've seen similar questions, but no answers or sample code to make these calls.
0
mamuscia
Asked:
mamuscia
  • 4
  • 3
  • 2
1 Solution
 
ahoffmannCommented:
on *ix it's as simple as
  exec("whatever &");
( also possible system(), passthru(), shell_exec() ...)
or more elegant using pcntl_fork(), see http://php.net/manual/en/function.pcntl-fork.php
or probably simply using fork()

on windows ... have fun :-/  (example never tested):
pclose(popen("start whatever", "r"));
0
 
Ray PaseurCommented:
You can start the script with a POST-method request. I don't know if this is limited to *nix systems (I do not use Windows servers) but I find that it works well and enables me to deal with things like external web services that are balky and inconsistent in response time.  

For example, I use the geoio.com service to geo-locate my clients.  It requires a GET request to start it, and sometimes it hangs which makes the elegant simplicity of file_get_contents() useless.  So to solve the problem of the external hang, I make a POST request to my interface script, and then forget about the success or failure of the interface.  The interface makes the GET request to geoio and updates my data base if it succeeds.  And if it fails, I can live with the partially incomplete data, since it is just mapping data for "amusement" purposes, showing here:
http://www.landonbaseball.com/site_visitors.php

The code snippet is a teaching example of how to use cURL for POST requests.

<?php // RAY_curl_post_example.php
error_reporting(E_ALL);


// DEMONSTRATE HOW TO USE CURL POST TO START AN ASYNCHRONOUS PROCESS


function curl_post($url, $post_array=array(), $timeout=2, $error_report=FALSE)
{
    // PREPARE THE POST STRING
    $post_string = NULL;
    foreach ($post_array as $key => $val)
    {
        $post_string .= $key . '=' . urlencode($val) . '&';
    }
    $post_string = rtrim($post_string, '&');

    // PREPARE THE CURL CALL
    $curl = curl_init();
    curl_setopt( $curl, CURLOPT_URL,            $url         );
    curl_setopt( $curl, CURLOPT_HEADER,         FALSE        );
    curl_setopt( $curl, CURLOPT_POST,           TRUE         );
    curl_setopt( $curl, CURLOPT_POSTFIELDS,     $post_string );
    curl_setopt( $curl, CURLOPT_TIMEOUT,        $timeout     );
    curl_setopt( $curl, CURLOPT_RETURNTRANSFER, TRUE         );

    // EXECUTE THE CURL CALL
    $htm = curl_exec($curl);
    $err = curl_errno($curl);
    $inf = curl_getinfo($curl);

    // ON FAILURE
    if (!$htm)
    {
        // PROCESS ERRORS HERE
        if ($error_report)
        {
            echo "CURL FAIL: $url TIMEOUT=$timeout, CURL_ERRNO=$err";
            echo "<pre>\n";
            var_dump($inf);
            echo "</pre>\n";
        }
        curl_close($curl);
        return FALSE;
    }

    // ON SUCCESS
    curl_close($curl);
    return $htm;
}


// USAGE EXAMPLE CREATES ASSOCIATIVE ARRAY OF KEY=>VALUE PAIRS
$args["name"]  = 'Ray';
$args["email"] = 'Ray.Paseur@Gmail.com';

// ACTIVATE THIS TO SEE THE ARRAY OF ARGS
// var_dump($args);

// SET THE URL
$url = "http://LAPRBass.com/RAY_bounce_post.php";

// CALL CURL TO POST THE DATA
$htm = curl_post($url, $args, 3, TRUE);

// SHOW WHAT CAME BACK, IF ANYTHING
if ($htm)
{
    echo "<pre>";
    echo htmlentities($htm);
}
else
{
    echo "NO RESPONSE YET FROM $url -- MAYBE BECAUSE IT IS RUNNING ASYNCHRONOUSLY";
}

Open in new window

0
 
mamusciaAuthor Commented:
Ray,
Not sure how this is working, but it does. My calling script continues without holding up the user and the script I call with CURL completes.  I know this is not asynchronous really, but it is doing what I want in both Windows and Linux environments.  Thanks for the technique.
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
Ray PaseurCommented:
What was wrong with the answer?
0
 
mamusciaAuthor Commented:
Nothing wrong per say, but it's not really starting a parallel asynch task as I wanted. It works, but that's because we don't care what the output is and don't do anything if we don't get it.
0
 
Ray PaseurCommented:
OK, then tell me what this means:  this is not asynchronous really.  Perhaps you and I have different definitions of "asynchronous."

As I understand the issue, your file upload completes very fast, but the processing of the file takes a very long time, so much so, that the client is made to wait much longer for the processing than for the upload.  So you want to decouple the upload from the long, slow processing step.  In that sense it's not a description of an asynchronous task - it's a description of a sequential process involving two tasks.  There is nothing at all standing in the way of sending an email from the second script when it is completed.  You would want to be very careful about debugging this script because the client cannot see any browser output, but it's certainly not a case of "don't care."  In MY application, I don't care.  But that is not the same as saying the process is flawed in some way.
0
 
mamusciaAuthor Commented:
Well, you are correct. I apologize if it sounded like I didn't think the solution was good.  I do and I'm using it.  I understand what you're saying about sequential versus asynch processing. I just really wanted to understand how I start a PHP script from either LAMP or WAMP environment by calling PHP and passing it the script to run.  Kind of like we run CRON jobs. It starts a PHP instance and passes it the script name.  It runs completely standalone from any other script.  From what I understand of your solution, it essentially does the same thing and won't tie anything to the users login session, so that's really the equivalent of what I'm after.  Thanks for your knowledge, I've been trying all kinds of things to get it to work in Windows to no avail. The solution hoffmann gave about works for Linux.  Your solution works in both.
0
 
Ray PaseurCommented:
OK, good.  I thought maybe something was wrong because of the marked-down grade.  Glad it's OK, ~Ray
0
 
ahoffmannCommented:
ok, it works, but not as you asked for (and not as a computer should do it, IMHO;-)
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 4
  • 3
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now