我们在Windows服务器上运行PHP(确实存在许多问题的根源,但目前无法进行迁移)。有几点需要用户启动的操作才能启动一些需要一段时间的事情以及用户在成功或失败时不需要知道的事情,例如发送电子邮件或确认一些第三方帐户已更新。如果我可以用pcntl_fork()
分叉,这将非常简单,但PCNTL功能在Windows中不可用。
似乎我能得到的最接近的是做这种性质的事情:
exec( 'php-cgi.exe somescript.php' );
但是,这会复杂得多。我需要开始的行动依赖于已经存在于运行过程中的大量上下文;使用上面的例子,我需要找出基本数据并以某种方式将它提供给新脚本。如果我可以分叉,那只是让父进程提前返回,让孩子继续处理更多事情。
我发现有一些人在谈论他们自己在Windows上编译各种PCNTL函数的工作,但似乎没有任何东西可用(破坏的链接等)。
尽管this question实际上与我的名字相同,但似乎问题是执行超时比需要分叉更多。所以,我最好选择重构一下来处理调用php-cgi,还是有其他选择?
编辑:似乎exec()
对此不起作用,至少在没有我弄清楚它的其他方面的情况下,因为它等待直到调用返回。我想我可以使用START
,有点像exec( 'start php-cgi.exe somescript.php' );
,但它仍然会等到另一个脚本完成。
答案 0 :(得分:13)
installing psexec如何使用-d
(不要等待)option
exec('psexec -d php-cgi.exe somescript.php');
答案 1 :(得分:3)
获取PSExec并运行命令:
exec("psexec -d php-cgi.exe myfile.php");
答案 2 :(得分:1)
您可以创建一个守护程序/后台进程来运行代码(例如发送电子邮件),并且请求只需要将项目添加到队列中,让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>');
答案 3 :(得分:1)
PSTools是一个很好的补丁,但我将其留在这里:
如果您的服务器运行Windows 10并且具有最新更新,则可以安装Linux子系统,该子系统具有自己的支持本机分支的内核。
这是Microsoft正式支持的。
这是good guide的用法。
一旦安装了子系统本身,就需要在子系统上安装php。
您的Windows“ c:\”驱动器位于“ / mnt / c”下,因此您可以从支持分支的子系统中运行php(并且通过扩展,子系统的php可以使用pcntl_fork)。
示例:php /mnt/c/xampp/htdocs/test.php
如果您想直接从Windows命令行运行子系统的php,则只需使用“ wsl”命令即可。
假设您正在“ C:\ xampp \ htdocs \”下运行此文件
示例:wsl php main.php
“ wsl”命令将为您解析路径,因此您无需做任何黑魔法,如果您在c:\ xampp \ htdocs下调用该命令,则子系统会将其解析为“ / mnt / c / xampp / htdocs/"。
如果您将服务器作为 apache服务器运行,则实际上不需要执行任何其他操作,只需停止Windows apache服务器并启动linux服务器就可以了。 显然,您需要在子系统上安装所有缺少的php模块。