我们在Windows服务器上运行PHP(确实存在很多问题的源代码,但是迁移目前不是一种select)。 有几点,用户发起的行动需要启动一些需要一段时间的事情,而用户不需要知道它们是成功还是失败,比如发送电子邮件或确保某些事情第三方帐户更新。 如果我可以用pcntl_fork()
分叉,这将是非常简单的,但PCNTL函数在Windows中不可用。
看来我能得到的最接近的是做这种性质的事情:
exec( 'php-cgi.exe somescript.php' );
但是,这将会复杂得多。 我需要启动的动作依赖于运行过程中已经存在的很多环境; 使用上面的例子,我需要弄清楚基本数据,并以某种方式将其提供给新脚本。 如果我能够分叉,那么只需要让父进程尽早返回就可以了,让孩子在更多的事情上工作。
我发现有几个人在谈论他们自己的工作,获得Windows上编译的各种PCNTL函数,但似乎没有任何东西可用(断开链接等)。
尽pipe这个问题与我的名字实际上是一样的,但似乎问题是执行超时而不是分叉。 所以,我最好的select是重构一下处理调用php-cgi,还是有其他的select?
编辑:似乎exec()
将不会为此工作,至less不是没有我认为它的一些其他方面,因为它等待,直到调用返回。 我想我可以使用START
,有点像exec( 'start php-cgi.exe somescript.php' );
,但仍然等待另一个脚本完成。
如何安装psexec并使用-d
(不要等待) 选项
exec('psexec -d php-cgi.exe somescript.php');
获取PSExec并运行命令:
exec("psexec -d php-cgi.exe myfile.php");
您可以创建一个守护程序/后台进程来运行代码(例如发送电子邮件),并且请求只需要将项目添加到队列中,让deamon完成繁重的工作。
例如,一个文件send_emails.bat :
cls C:\PHP533\php.exe D:\web\server.php exit
打开Windows任务计划程序,并且每30分钟运行一次上面的send_emails.bat。 确保一次仅运行一个实例,或者可以以多个运行每个任务,或发送每个电子邮件两次。 我说30分钟,以防万一暂时中断(内存问题,数据库不可用等),它会重新开始每30分钟,而不是一个永无止境的过程,只是停止。 以下是一个骷髅守护进程…不完整或测试我只是输入一个例子:
<?php set_time_limit(60*30); // don't run $keepgoing = true; $timeout = time()+ 60*29; // 29 minutes while(time() < $timeout) { // grab emails from database $result = $db->query('select subject, body, to_email FROM email_queue'); if($result->num_rows == 0) { sleep(10); // so we are not taxing the database } else { while($row = $result->fetch_assoc()) { // send email } } } exit; ?>
最后,您只需要将该项添加到数据库队列中的请求,并让守护进程处理繁重的工作。
$db->query('insert into email_queue(to,subject,body) values ('customer@email.com','important email','<b>html body!</b>');