PHP设置超时的脚本与系统调用,set_time_limit不工作 [英] PHP set timeout for script with system call, set_time_limit not working
问题描述
我有一个命令行PHP脚本,使用foreach数组的每个成员运行wget请求。这个wget请求有时可能需要很长时间,所以我想要能够设置超时杀死脚本,如果它超过15秒例如。我有PHP的safemode被禁用,并尝试set_time_limit(15)在脚本的早期,但它无限期继续。 更新:感谢Dor指出这是因为set_time_limit()不尊重system()调用。
I have a command-line PHP script that runs a wget request using each member of an array with foreach. This wget request can sometimes take a long time so I want to be able to set a timeout for killing the script if it goes past 15 seconds for example. I have PHP safemode disabled and tried set_time_limit(15) early in the script, however it continues indefinitely. Update: Thanks to Dor for pointing out this is because set_time_limit() does not respect system() calls.
其他方式杀死脚本15秒后执行。但是,我不知道是否可以检查一个脚本在同一时间在一个wget请求的中间运行的时间(do while循环不工作)。可能用一个定时器分配一个进程,并设置它在一定时间后杀死父级?
So I was trying to find other ways to kill the script after 15 seconds of execution. However, I'm not sure if it's possible to check the time a script has been running while it's in the middle of a wget request at the same time (a do while loop did not work). Maybe fork a process with a timer and set it to kill the parent after a set amount of time?
感谢任何提示!
更新:
下面是我的相关代码。 $ url是从命令行传递的,是一个由多个URL组成的数组(对不起初不发布):
Update: Below is my relevant code. $url is passed from the command-line and is an array of multiple URLs (sorry for not posting this initially):
foreach( $url as $key => $value){
$wget = "wget -r -H -nd -l 999 $value";
system($wget);
}
推荐答案
--timeout和time()。
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.
例如:
$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);
}
}
注意:如果不使用-t,
Note: if you don't use -t, wget will try 20 times, each waiting --timeout seconds.
下面是一些使用proc_open / proc_terminate(@Josh的建议)的示例代码:
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");
}
}
这篇关于PHP设置超时的脚本与系统调用,set_time_limit不工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!