PHP 后台进程
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/265073/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PHP Background Processes
提问by zuk1
I'm trying to make a PHP script, I have the script finished but it takes like 10 minutes to finish the process it is designed to do. This is not a problem, however I presume I have to keep the page loaded all this time which is annoying. Can I have it so that I start the process and then come back 10mins later and just view the log file it has generated?
我正在尝试制作一个 PHP 脚本,我已经完成了脚本,但是完成它设计的过程大约需要 10 分钟。这不是问题,但是我认为我必须一直保持页面加载,这很烦人。我可以拥有它以便我开始该过程,然后在 10 分钟后返回并查看它生成的日志文件吗?
回答by bastiandoeen
Well, you can use "ignore_user_abort(true)"
好吧,你可以使用“ ignore_user_abort(true)”
So the script will continue to work (keep an eye on script duration, perhaps add "set_time_limit(0)")
所以脚本会继续工作(注意脚本持续时间,或者添加“ set_time_limit(0)”)
But a warning here: You will not be able to stop a script with these two lines:
但是这里有一个警告:您将无法使用这两行来停止脚本:
ignore_user_abort(true);
set_time_limit(0);
Except you can directly access the server and kill the process there! (Been there, done an endless loop, calling itself over and over again, made the server come to a screeching stop, got shouted at...)
除了您可以直接访问服务器并在那里终止进程!(去过那里,做了一个无限循环,一遍又一遍地调用自己,让服务器停止尖叫,被大喊......)
回答by Gary Richardson
Sounds like you should have a queue and an external script for processing the queue.
听起来您应该有一个队列和一个用于处理队列的外部脚本。
For example, your PHP script should put an entry into a database table and return right away. Then, a cron running every minute checks the queue and forks a process for each job.
例如,您的 PHP 脚本应该将一个条目放入数据库表中并立即返回。然后,每分钟运行一次的 cron 检查队列并为每个作业派生一个进程。
The advantage here is that you don't lock an apache thread up for 10 minutes.
这里的优点是您不会将 apache 线程锁定 10 分钟。
回答by Christopher Lightfoot
I had lots of issues with this sort of process under windows; My situation was a little different in that I didn't care about the response of the "script"- I wanted the script to start and allow other page requests to go through while it was busy working away.
我在 Windows 下的这种进程有很多问题;我的情况有点不同,因为我不关心“脚本”的响应 - 我希望脚本启动并允许其他页面请求在它忙于处理时通过。
For some reason; I had issues with it either hanging other requests or timing out after about 60 seconds (both apache and php were set to time out after about 20 minutes); It also turns out that firefox times out after 5 minutes (by default) anyway so after that point you can't know what's going on through the browser without changing settings in firefox.
因为某些原因; 我遇到了问题,要么挂起其他请求,要么在大约 60 秒后超时(apache 和 php 都设置为在大约 20 分钟后超时);事实证明,无论如何,firefox 会在 5 分钟(默认情况下)后超时,因此在那之后,如果不更改 firefox 中的设置,您将无法通过浏览器知道发生了什么。
I ended up using the process open and process close methods to open up a php in cli mode like so:
我最终使用 process open 和 process close 方法在 cli 模式下打开一个 php,如下所示:
pclose(popen("start php myscript.php", "r"));
pclose(popen("start php myscript.php", "r"));
This would ( using start ) open the php process and then kill the start process leaving php running for however long it needed - again you'd need to kill the process to manually shut it down. It didn't need you to set any time outs and you could let the current page that called it continue and output some more details.
这将(使用 start )打开 php 进程,然后终止启动进程,让 php 运行所需的时间 - 同样,您需要终止该进程以手动关闭它。它不需要您设置任何超时,您可以让调用它的当前页面继续并输出更多详细信息。
The only issue with this is that if you need to send the script any data, you'd either do it via another source or pass it along the "command line" as parameters; which isn't so secure.
唯一的问题是,如果您需要向脚本发送任何数据,您要么通过另一个来源执行此操作,要么将其作为参数通过“命令行”传递;这不是那么安全。
Worked nicely for what we needed though and ensures the script always starts and is allowed to run without any interruptions.
很好地满足了我们的需要,并确保脚本始终启动并允许运行而不会中断。
回答by warren
This may be of assistance, also: Asynchronous shell exec in PHP
这可能也有帮助:Asynchronous shell exec in PHP
回答by warren
I think shell_exec command is what you are looking for.
我认为 shell_exec 命令就是你要找的。
However, it is disables in safe mode.
但是,它在安全模式下被禁用。
The PHP manual article about it is here: http://php.net/shell_exec
关于它的 PHP 手册文章在这里:http: //php.net/shell_exec
There is an article about it here: http://nsaunders.wordpress.com/2007/01/12/running-a-background-process-in-php/
这里有一篇关于它的文章:http: //nsaunders.wordpress.com/2007/01/12/running-a-background-process-in-php/
回答by Ronald Conco
There is another option which you can use, run the script CLI...It will run in the background and you can even run it as a cronjob if you want.
您可以使用另一个选项,运行脚本 CLI...它将在后台运行,如果需要,您甚至可以将其作为 cronjob 运行。
e.g
例如
> #!/usr/bin/php -q
<?php
//process logs
?>
This can be setup as a cronjob and will execute with no time limitation....this examples is for unix based operation system though.
这可以设置为一个 cronjob 并且将在没有时间限制的情况下执行......不过这个例子适用于基于 Unix 的操作系统。
FYI I have a php script running with an infinite loop which does some processing and has been running for the past 3 months non stop.
仅供参考,我有一个无限循环运行的 php 脚本,它进行一些处理,并且在过去 3 个月中一直在不停地运行。
回答by Greg
You could use ignore_user_abort()- that way the script will continue to run even if you close your browser or go to a different page.
您可以使用ignore_user_abort()- 这样即使您关闭浏览器或转到其他页面,脚本也会继续运行。
回答by Gowri
Think about Gearman
想想Gearman
Gearman is a generic application framework for farming out work to multiple machines or processes. It allows applications to complete tasks in parallel, to load balance processing, and to call functions between languages. The framework can be used in a variety of applications, from high-availability web sites to the transport of database replication events.
This extension provides classes for writing Gearman clients and workers. - Source php manual
Gearman 是一个通用的应用程序框架,用于将工作分给多个机器或流程。它允许应用程序并行完成任务、负载平衡处理以及在语言之间调用函数。该框架可用于各种应用程序,从高可用性网站到数据库复制事件的传输。
此扩展提供用于编写 Gearman 客户端和工作器的类。- 源 php 手册
Offical website of Gearman
的官方网站的Gearman
回答by RafaSashi
In addition to bastiandoeen's answer you can combine ignore_user_abort(true);with a cUrl request.
除了bastiandoeen的回答,您可以结合ignore_user_abort(true);使用cUrl作者请求。
Fake a request abortion setting a low CURLOPT_TIMEOUT_MSand keep processing after the connection closed:
将请求中止设置为低CURLOPT_TIMEOUT_MS并在连接关闭后继续处理:
function async_curl($background_process=''){
//-------------get curl contents----------------
$ch = curl_init($background_process);
curl_setopt_array($ch, array(
CURLOPT_HEADER => 0,
CURLOPT_RETURNTRANSFER =>true,
CURLOPT_NOSIGNAL => 1, //to timeout immediately if the value is < 1000 ms
CURLOPT_TIMEOUT_MS => 50, //The maximum number of mseconds to allow cURL functions to execute
CURLOPT_VERBOSE => 1,
CURLOPT_HEADER => 1
));
$out = curl_exec($ch);
//-------------parse curl contents----------------
//$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
//$header = substr($out, 0, $header_size);
//$body = substr($out, $header_size);
curl_close($ch);
return true;
}
async_curl('http://example.com/background_process_1.php');
NB
NB
If you want cURL to timeout in less than one second, you can use CURLOPT_TIMEOUT_MS, although there is a bug/"feature" on "Unix-like systems" that causes libcurl to timeout immediately if the value is < 1000 ms with the error "cURL Error (28): Timeout was reached". The explanation for this behavior is:
[...]
The solution is to disable signals using CURLOPT_NOSIGNAL
如果您希望 cURL 在不到一秒的时间内超时,您可以使用 CURLOPT_TIMEOUT_MS,尽管“类 Unix 系统”上存在一个错误/“功能”,如果值 < 1000 毫秒,则会导致 libcurl 立即超时并出现错误“ cURL 错误 (28):已达到超时”。这种行为的解释是:
[...]
解决方案是使用 CURLOPT_NOSIGNAL 禁用信号
pros
优点
- No need to switch methods (Compatible windows & linux)
- No need to implement connection handling via headers and buffer (Independent from Browser and PHP version)
- 无需切换方法(兼容 windows & linux)
- 无需通过头和缓冲区实现连接处理(独立于浏览器和 PHP 版本)
cons
缺点
- Need curl extension
- 需要卷曲扩展
Resources
资源
回答by Nader
Zuk.
祖克。
I'm pretty sure this will work:
我很确定这会奏效:
<?php
pclose(popen('php /path/to/file/server.php &'));
echo "Server started. [OK]";
?>
The '&' is important. It tells the shell not to wait for the process to exit.
'&' 很重要。它告诉 shell 不要等待进程退出。
Also You can use this code in your php (as "bastiandoeen" said)
您也可以在 php 中使用此代码(如“bastiandoeen”所说)
ignore_user_abort(true);
set_time_limit(0);
in your server stop command:
在您的服务器停止命令中:
<?php
$output;
exec('ps aux | grep -ie /path/to/file/server.php | awk \'{print }\' | xargs kill -9 ', $output);
echo "Server stopped. [OK]";
?>

