真功夫!做个高端的东西,加入我们做一个任务系统,这个系统可以帮我们在后台完成一大波(注意是大波)的数据处理,那我们自然会想到多开几个processes去分别处理这些同时,我们无法执行phptask.php,终端挂了。如果不小心关闭了终端,任务就会失败,所以我们需要实现程序的守护进程。好的,我们开始吧!首先,我们的第一步是对程序进行守护进程!//设置umask为0,使得当前进程创建的文件权限为777umask(0);$pid=pcntl_fork();if($pid<0){exit('fork错误。');}elseif($pid>0){//主进程退出exit();}//子进程继续执行//最关键的一步是执行setsid函数!if(!posix_setsid()){exit('setsid错误。');}//理论上fork一次就够了//然而,对于第二次fork,这里的历史渊源是这样的:在基于系统V的系统中,通过再次fork,父进程退出,子进程继续运行//确保形成的守护进程永远不会成为会话领导进程,并且不会有控制终端。$pid=pcntl_fork();if($pid<0){exit('分叉错误');}elseif($pid>0){//主进程退出exit;}//子进程继续执行//给进程重命名cli_set_process_title('phpmasterprocess');加入我们fork出5个子进程来完成这些任务,然后fork出5个子进程,父进程负责这5个子进程的状态。//由于*NIX好像没有(如果有请告知)获取父进程fork出来的所有子进程ID的功能,所以这个需要自己保存$child_pid=[];//父进程安装SIGCHLDSignalhandler并分发pcntl_signal(SIGCHLD,function(){//这里注意globalchild_pid要全局化,否则读取后数组为空,具体原因可以考虑global$child_pid;//如果子进程数大于0,也就是说如果还有子进程存活,没有退出,则执行回收$child_pid_num=count($child_pid);if($child_pid_num>0){//循环子进程数组foreach($child_pidas$pid_key=>$pid_item){$wait_result=pcntl_waitpid($pid_item,$status,WNOHANG);//如果子进程回收成功,则必须去掉其进程ID来自child_pidif($wait_result==$pid_item||-1==$wait_result){unset($child_pid[$pid_key]);}}}});//fork出5个子进程,并重命名每个子进程for($i=1;$i<=5;$i++){$_pid=pcntl_fork();如果($_pid<0){退出();}elseif(0==$_pid){//重命名子进程cli_set_process_title('phpworkerprocess');//啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦LaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaLaPleaseBeHerePleaseGoHere写你的业务代码不会fork5但多于5个任务进程e退出();}elseif($_pid>0){//将forked任务进程的进程ID保存到数组中$child_pid[]=$_pid;}}//主进程继续发送信号while(true){pcntl_signal_dispatch();//每次休眠一秒sleep(1);}[原文地址:https://blog.ti-node.com/blog...]
