shell_exec() timeout management & exec()
I would suggest you look into using proc_open
. You can configure it to return a stream resource, manually keep a timer, and if the timer expires before the process completes, you can terminate it with proc_terminate
. If it does complete before the timer expires, then you can use proc_close
then stream_get_contents
to grab the data that would have otherwise been written to stdout.
See http://www.php.net/manual/en/function.proc-open.php
set time limit on java code execution through shell_exec
You can do it in 3 ways:
1) Call pcntl_fork in PHP and check the timeout in parent process. Kill it if it exceeds using linux kill command.
2) Include timeout in a bash script that you will invoke using shell_exec, see this example:
http://www.bashcookbook.com/bashinfo/source/bash-4.0/examples/scripts/timeout3
3) Use proc_open / proc_terminate functions
Personally I would go with number 3, it's the cleanest. If you need quick and dirty, use number 2.
PHP set timeout for script with system call, set_time_limit not working
You can use a combination of "--timeout" and time(). Start off by figuring out how much time you have total, and lower the --timeout as your script runs.
For example:
$endtime = time()+15;
foreach( $url as $key => $value){
$timeleft = $endtime - time();
if($timeleft > 0) {
$wget = "wget -t 1 --timeout $timeleft $otherwgetflags $value";
print "running $wget<br>";
system($wget);
} else {
print("timed out!");
exit(0);
}
}
Note: if you don't use -t, wget will try 20 times, each waiting --timeout seconds.
Here's some example code using proc_open/proc_terminate (@Josh's suggestion):
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("pipe", "w")
);
$pipes = array();
$endtime = time()+15;
foreach( $url as $key => $value){
$wget = "wget $otherwgetflags $value";
print "running $wget\n";
$process = proc_open($wget, $descriptorspec, $pipes);
if (is_resource($process)) {
do {
$timeleft = $endtime - time();
$read = array($pipes[1]);
stream_select($read, $write = NULL, $exeptions = NULL, $timeleft, NULL);
if(!empty($read)) {
$stdout = fread($pipes[1], 8192);
print("wget said--$stdout--\n");
}
} while(!feof($pipes[1]) && $timeleft > 0);
if($timeleft <= 0) {
print("timed out\n");
proc_terminate($process);
exit(0);
}
} else {
print("proc_open failed\n");
}
}
Best way to manage long-running php script?
Certainly it can be done with PHP, however you should NOT do this as a background task - the new process has to be dissociated from the process group where it is initiated.
Since people keep giving the same wrong answer to this FAQ, I've written a fuller answer here:
http://symcbean.blogspot.com/2010/02/php-and-long-running-processes.html
From the comments:
The short version is
shell_exec('echo /usr/bin/php -q longThing.php | at now');
but the reasons "why", are a bit long for inclusion here.
Update +12 years
While this is still a good way to invoke a long running bit of code, it is good for security to limit or even disable the ability of PHP in the webserver to launch other executables. And since this decouples the behaviour of the log running thing from that which started it, in many cases it may be more appropriate to use a daemon or a cron job.
Related Topics
Interview Question: How to Have an Echo Before Header
Implementing Oauth2 Login, Fatal Error: Class 'Google_Service' Not Found
Access MySQL Field's Comments with PHP
Php/Apache: PHP Fatal Error: Call to Undefined Function MySQL_Connect()
PHP String Comparasion to 0 Integer Returns True
Macd Function Returning Incorrect Values
PHP Associative Array Key Order (Not Sort)
PHP String Concatenation - "$A $B" VS $A . " " . $B - Performance
What Is Laravel Render() Method For
MySQL Password Hashing Method Old VS New
How to Access the Google Spreadsheets API in PHP
PHP Foreach() with Arrays Within Arrays
Switch of PHP Versions Not Working on MAC
Call to Undefined Function Oci_Connect, PHP_Oci8_12C.Dll, Windows 8.1, PHP5.6.6