Reputation: 5957
I'm currently launching an asynchronous job with PHP to perform some tests.
To make it work, I found on SO some tips, like the use of popen
and start
:
$commande = "testu.bat";
$pid = popen('start /B ' . $commande, 'r');
$status = pclose($pid);
The testu.bat
's folder is in my user PATH.
This script performs some task, and to control it's execution, it should generates a log file, but I never get it.
Whereas if I just remove the /B
option, it works fine and I get my log file.
Did I miss something about background execution? How can I catch the error informations when it is running in the background?
Upvotes: 2
Views: 2114
Reputation: 575
Just for some people seeking this trick to works, in my case it just needs to activate the PHP directive ignore_user_abort in php.ini or by the PHP platform function.
Without this activated, the process is killed by pclose() without finishing the job.
Upvotes: 1
Reputation:
Your problem is most likely properly solved by using a queue system. You insert a job into a queue that a background process picks up and works on. In this way the background task is completely independent of the HTTP request that initiated the task - but you can still monitor its progress.
The two most popular software packages that can help you in your scenario:
Note that implementing a queuing solution is not a 5 minute prospect, but it is technically the right approach for this sort of situation. For a company product this is the only viable approach; for a personal project where you just want something to work, there is a level of commitment required to see it through for the first time. If you're looking to expand your development horizons, I strongly suggest you give the queue a shot.
Upvotes: 0
Reputation: 20174
It appears you are operating under the assumption that the /B
switch to the start
command means "background". It does not. From the start
usage:
B Start application without creating a new window. The
application has ^C handling ignored. Unless the application
enables ^C processing, ^Break is the only way to interrupt
the application.
Processes launched by start
are asynchronous by default. Since that appears to be what you want, just run the command without the /B
switch.
Upvotes: 4
Reputation: 6580
In my opinion start
launches the specified command by creating a new prcoess in the "background". Therefore the execution of start
itself "just" starts the second process and exists immediately.
However, using the /B
switch, the command to be executed will be excuted in the context of the start
process. Therefore the execution of the start
process takes longer. Now what I suspect is that executing pclose
terminates the start
process and as a result of this you don't get your log file.
Maybe one solution (not testet though) could be executing something like
start /B cmd "/C testu.bat"
where start
just tries to execute cmd
and cmd
gets /C testu.bat
as parameter which is the "command" it shall execute.
Another thought:
What happens if you don't call $status = pclose($pid);
?
Upvotes: 1
Reputation: 462
I'm not quite sure about your goal here, but here are some info you might use:
for figuring out background errors, you may find these functions useful:
set_exception_handler();
set_error_handler();
register_shutdown_function();
Of course write out the errors they catch into some file.
If you do not need any data back from your requests, you can simply use:
fsockopen()
curl
and give them a short timeout (10 milisec). The scripts will run in the backround.
Alternatively if you do need the data back, you can either put it into a database and set up a loop that checks if the data has already been inserted, or simply output it into a file and check for its existence.
Upvotes: 1
Reputation: 1444
Interesting one... Ok, here's what I think is going on: Because you run the task in the background, the PHP script will just carry on, it is not waiting for testu.bat to return anything...
Or put another way, popen does what it was instructed to do, which is starting the task in the background (which it does) but then control is handed immediately back to PHP, whilst the log file is still being created in the background and the php script carries on at the same time...
What I would do in this case is let testu.bat call the php script (or another PHP script) in a callback type fashion once it has done its processing, in a similar way as in Javascript you would use callbacks for asynchromous Ajax calls...
Maybe provide the callback script command as a parameter to testu.bat..?
Hope this is of any help...
Upvotes: 1