Execute PHP Script in a PHP Page without waiting

I found this method to execute a php script within a php page without making the user wait until it completes executing.

shell_exec("php Server.php > /dev/null 2>/dev/null &")

Open in new window


What's going on in this command?  

1. Do I need to have the full path the php script or does it execute from the path of the current php page?  
2. Why is there /dev/null 2 etc... in there?  
3. How could I pass a $_GET parameter to it?
LVL 12
Nathan RileyFounderAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Ray PaseurCommented:
Shell_Exec() is one of the program execution functions.  It lets you run command-line statements, and gives you back the console output in a PHP string variable.

It sounds like you're looking for asynchronous execution of a PHP script?  What do you want the async script to accomplish?
0
Nathan RileyFounderAuthor Commented:
I have a script that runs already against a database table by passing it some ID's.  

I want to run this script on another page, but the script runs for about 60 seconds and I don't want the user to have to wait for 60 seconds for the page to load, so I want to kick off that script and continue loading the page.
0
Nathan RileyFounderAuthor Commented:
Looks like I may want this command:

exec("php script.php > /dev/null &");

Open in new window


Still looking into how I pass it a GET variable.
0
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

Nathan RileyFounderAuthor Commented:
I tried calling like this:
exec('php cronInsightsOD.php "'.addslashes($insightID).'"');

Open in new window


Then in my script picking up the variable like:
$insightID = stripslashes($argv[1]);

Open in new window


Doesn't appear to work though.
0
Nathan RileyFounderAuthor Commented:
Hmm...if I run from a putty window
php cronInsightsOD.php 97

Open in new window


It executes as expected.
0
Ray PaseurCommented:
Let's try the "hello world" example.  Try saving this as "foo.php" and running it from the command line.
<?php echo 'Hello World';

Open in new window

Next let's see if we can find request variables.
<?php echo 'Hello World';
var_dump($_REQUEST);

Open in new window

Using PHP to cause system executions always makes me nervous.  Are you open to the idea of using cURL POST to start the script?  Or maybe you can cache the results of the long-running job?
0
Nathan RileyFounderAuthor Commented:
Ah, good call.  I don't know why I didn't think of curl.  Much better solution, thanks!
0
Nathan RileyFounderAuthor Commented:
Ah, but it still seems to make the page wait until the it fully executes.

                $url = 'cronInsightsOD.php?insightID='.$insightID;
                $ch = curl_init($url);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
                $url = curl_exec($ch);
                curl_close($ch);

Open in new window


Is there a method in CURL to just send the GET request and move on without waiting for a response?
0
Ray PaseurCommented:
Yes, I think you can turn the GET request into a POST request and set a short time out.  I believe that cURL POST requests can proceed independently of the initiating script.  This means you would need to change the cronInsightsOD.php script to use $_REQUEST instead of $_GET.
0
hieloCommented:
Login through putty and execute the following command:
which php

and the use the output of the above command as the first part of your command.  For the sake of clarity, let's say that the output of the above command is /usr/bin/php.  Also, let's say that your file is located at /var/www/htdocs/cronInSightsOD.php.  So your command should be:
shell_exec('/usr/bin/php -f /var/www/htdocs/cronInSightsOD.php ' . escapeshellarg($_GET['ID']) . ' > /dev/null 2>/dev/null &');

Open in new window


then in cronInSightsOD.php, to retrieve the ID, dereference $argv[1]:
<?php
#!/usr/bin/php
$ID = $argv[1];

// do whatever you need to do with $ID
mail('youremail@yourcompany.com','Testing','Received ID: ' . $ID, "From: you@yourcompany.com");

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Julian HansenCommented:
To answer the questions asked:

1. Do I need to have the full path the php script or does it execute from the path of the current php page?

The path must be the full path or relative to the calling script

2. Why is there /dev/null 2 etc... in there?  

/dev/null is the Unix trash can - what it is saying is send any output from the program into the bottomless garbage bin rather than send it to the screen or other output device

The reason there are two in there is because there are different outputs that can be redirected as follows:
> file redirects stdout to file
1> file redirects stdout to file
2> file redirects stderr to file
&> file redirects stdout and stderr to file

Open in new window


3. How could I pass a $_GET parameter to it?
Simple working sample

Primary Script
<?php
$path_to_script = "./";

// CHECK FOR GET PARAMETER 'me'
if (isset($_GET['me'])) {
  
  // EXTRACT AND SANITISE
  $param = (int)$_GET['me'];

  // EXEC APPLICATION SENDING OUTPUT TO /dev/null ON LINUX
  // FOR WINDOWS SYSTEMS > NUL
  exec('php ' . $path_to_script . "/script.php " . $param . " > /dev/null 2> /dev/null");
}

Open in new window


Script.php code
<?php
// CHECK argc HOLDS NUMBER OF PARAMS SENT TO SCRIPT
// VALUE WILL BE 1 OR MORE. FIRST PARAMETER (argv[1]) IS ALWAYS 
// NAME OF SCRIPT SO PARAMETERS PASSED TO SCRIPT WILL
// BE FROM argv[1] ONWARDS
if ($argc > 1) {

  // CREATE A MESSAGE
  $resp = "You called me with {$argv[1]}";

  // WRITE IT TO A FILE TO PROVE IT DID SOMETHING
  file_put_contents('script.txt', $resp);
}
else {
	file_put_contents('script.txt', "Fubar");
}

Open in new window


That should provide the basic skeleton of the requirement.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.