Viewed   91 times

I'm trying to setup a php trigger file that will set off a background process. (see this question)

I'm doing this on a Windows Wampserver environment.

So for example I have trigger.php that runs the exec function that calls for my backgroundProcess.php to be parsed and executed.

However the problem is that my trigger.php file is waiting for the exec() command to finish running backgroundProcess.php before it stops. The background process runs for about 20-30 seconds, and trigger.php is waiting all that time until backgroundProcess.php has fully finished.

Is that making sense? Here is the trigger.php file that runs the exec() command

exec('C:wampbinphpphp'.phpversion().'php.exe -f C:pathtobackgroundProcess.php > C:wampbinphpphp'.phpversion().'devnull &');

Basically, I'm wanting trigger.php to just trigger off the backgroundProcess and not wait around for it to finish.


EDIT

Problem solved with the following command:

$WshShell = new COM("WScript.Shell");
$oExec = $WshShell->Run("C:wampbinphpphpVERSIONNUMBERphp-win.exe -f C:/wamp/www/path/to/backgroundProcess.php", 0, false);

 Answers

2

Problem solved with the following command:

$WshShell = new COM("WScript.Shell");
$oExec = $WshShell->Run("C:wampbinphpphpVERSIONNUMBERphp-win.exe -f C:/wamp/www/path/to/backgroundProcess.php", 0, false);
Friday, December 9, 2022
2

My guess is that what you are trying to do is not directly possible. By backgrounding the process, you are letting your PHP script continue (and potentially exit) before a result exists.

A work around is to have a second PHP (or Bash/etc) script that just does the command execution and writes the result to a temp file.

The main script would be something like:

$resultFile = '/tmp/result001';
touch($resultFile);
exec('php command_runner.php '.escapeshellarg($resultFile).' > /dev/null 2>&1 &');

// do other stuff...    

// Sometime later when you want to check the result...
while (!strlen(file_get_contents($resultFile))) {
    sleep(5);
}
$result = intval(file_get_contents($resultFile));
unlink($resultFile);

And the command_runner.php would look like:

$outputFile = $argv[0];
exec('badcommand > /dev/null 2>&1', $output, $result);
file_put_contents($outputFile, $result);

Its not pretty, and there is certainly room for adding robustness and handling concurrent executions, but the general idea should work.

Tuesday, December 13, 2022
 
4

You will have to install an extra extension, but found the solution located at Uniformserver's Wiki.

UPDATE

After some searching you might look into tasklist which coincidently, you may be able to use with the PHP exec command to get what you are after.

Tuesday, November 15, 2022
 
tanz87
 
2

The above approach that I was trying to achieve didn't seem possible to be implemented in Windows. Many methods listed in the questions are either removed or modified. I then moved on to a workaround involving use of AJAX.

I execute the controller method as an ajax request and give a count to it which increments with each new AJAX request. Each request can be aborted though the processing will continue but ultimately results matter in my project even if they are taken incomplete. And if the browser is open then that request may complete and later on the user can see the complete result.

On stopping the processing of a task a CANCELLED icon is shown and a link pointing to result page is shown which displays the results generated before the task was cancelled. On AJAX fails or AJAX success I send back the count of the task from server to client which was sent by the client to server. Thus results are displayed for a unique task and don't get messed up.

But there is no tracking of how much a certain task has progressed. The time taken for execution cannot be identified. Thus, this approach works for me but has some drawbacks. The main aim was the user should not be waiting while some task is in progress and that is somehow achieved by the above workaround.

Tuesday, November 8, 2022
 
4

As @glenn-jackman pointed out, the use of fileevent is preferred (because it should work everywhere).

proc handle_bgexec {callback chan} {
    append ::bgexec_data($chan) [read $chan]
    if {[eof $chan]} {
        # end of file, call the callback
        {*}$callback $::bgexec_data($chan)
        unset ::bgexec_data($chan)
    }
}

proc bgexec {callback args} {
    set chan [open "| $args" r]
    fconfigure $chan -blocking false
    fileevent $chan readable [list handle_bgexec $callback $chan]
    return
}

Invoke this as bgexec job_done cmd /c start /wait cmd /c make all-all. job_done gets called with the output of the command after it finishes.

It is also possible to use threads for this things, but this requires a threaded tcl build (which is now default for all platforms AFAIK, but older versions of Tcl esp. under unix don't build a threaded Tcl by default.) and the Thread package (which is included by default). An approach to use it with Threads would be:

thread::create "[list exec cmd /c start /wait cmd /c make all-all];[list thread::send [thread::id] {callback code}];thread::exit"

If you need to call this on a regular basis it might be worth to use only one worker thread instead of creating a new one for each job.

Edit: Add /wait as parameter for start the keep the first cmd running.

cmd /c start /wait cmd /c make all-all
Monday, August 8, 2022
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :