※ 引述《b90022790 (PomeloLaLa)》之铭言:
: 各位php板上的各位前辈好!
: 目前在架设一个简单的订单系统,有个功能无法顺利完成,希望前辈们能给些意见,谢谢
: 环境:php7.4.1、 MySQL、CentOS 6.8
: 功能:当商家按钮确认订单后,除了修改MySQL内容外,希望能够寄mail通知客户
: 问题:使用PHPMailer接gmail SMTP,然而速率过慢,商家的client端需要等待执行完毕
: 才能看到确认后的结果,希望能先让商家看到结果,寄信的功能在服务器背景执行。
: 试过的解决方式:先写一个send.php专门处理寄信的功能,在商家client的页面直接显示
: 确认订单后的结果画面,并在商家该php页面使用system()执行send.php,程式码如下:
: system("php send.php user"); //user为收信者参数
: 然而这仍然会等待执行完才会回responce。
: 使用“php 背景执行 超时”当关键字,采用将结果输出到.out,改system()程式码如下:
: system("php send.php user > MAIL.out");
: 然而这样却变成连寄信都没有执行就结束了。
: 希望前辈们能给一些如何处理该功能的意见,以及为何该system()无法正常执行
: 谢谢各位前辈!还请各位指点!!
php send.php user > MAIL.out
只会把 send.php 的输出(stdout)写进 MAIL.out,没有异步执行的效果
结果会不一样,也许是 wwwuser 没有资料夹写入权限,所以指令直接喷掉
要异步执行东西,直觉是 pcntl_fork()
$pid = pcntl_fork();
if ($pid === 0) {
// 我是 fork 出来的 process,不会卡住娘亲 process 执行
// 在这里寄信
system("php send.php user");
exit; // 寄完信就 exit,不然会一路执行到网页内容整个印出来
}
// 我是原本的 process,或是 fork 失败
// 继续做网页该做的事情
缺点是不熟的人容易不小心写出惊人的 bug
像是不小心 fork 了一万个 process 然后整台机器被 process 噎死
这算是妖术,土炮或是很小的东西可以这么干
如果工作上有人对网页服务发这样的 MR 给我 review,我会热烈地给予关切
推荐做法是,不要在网页里面直接处理这件事
把你要寄信的资料先记录在某个地方,档案也好 DB 也好。
然后跑一只其他的程式在后面等著,或是设定 cron job 定时去读
看到有资料的时候依序寄信然后把资料清空,如果没有新资料就回去睡觉
更上道的做法,是去研究 message queue / job queue
============
另,如果想用 PHP 写 cli 指令,有个小地方可以参考
像这样透过第一行的 hashbang 告诉 shell 要呼叫 php 来执行这只程式
#!/usr/bin/env php
<?php
echo "I am a command\n";
然后把这只 php 设定为可执行档案
$ chmod +x command.php
就可以把这只 code 当成 shell script 来跑了
$ ./command.php
I am a command