作者:手机用户2502883445 | 来源:互联网 | 2020-08-08 22:57
守护进程作为一种常驻进程服务,很常见,例如PHP-FPM,NGINX,REDIS,都需要一个父进程来支持整个服务。但是用PHP编写守护进程不多见,今天就来用PHP来实现一下。
守护进程
守护进程作为一种常驻进程服务,很常见,例如 PHP-FPM, NGINX,REDIS,都需要一个父进程来支持整个服务。但是用 PHP 编写守护进程不多见,今天就来用 PHP 来实现一下。
步骤
● fork 子进程
● 父进程退出
● 设置新的会话
● 重置文件掩码
● 关闭标准输入输出
实现
我们对着以上的步骤来实现,在这之前需要 pcntl 和 posix 扩展,请确保安装了。
function daemon() {
$pid = pcntl_fork();
// fork 失败
if ($pid <0) {
exit(&#39;fork failed&#39;);
} else if ($pid > 0) {
// 退出父进程
exit(0);
}
// 设置新的会员
// setsid 有几个注意点
// 不能是进程组的组长调用
// 对于进程组组员调用会产生新的会话和进程组,并成为该进程组的唯一成员,调用的进程将脱离终端
if (posix_setsid() <0) {
exit(&#39;set sid failed&#39;);
}
// 重置文件掩码
umask(0);
// 切换工作目录
chdir(&#39;/&#39;);
// 关闭标准输入输出
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);
}
细节
// 获取进程ID
var_dump(posix_getpid());
// 获取进程组ID
var_dump(posix_getpgid(posix_getpid()));
// 获取进程会话ID
var_dump(posix_getsid(posix_getpid()));
三者结果相同,说明了该进程即使进程组的组长,也是会话首领。
为什么需要 umask (0)
当你在 linux 调用 umask 的时候你会看到一个掩码值,这个掩码决定了你创建文件权限范围,例如本人当前机器的 umask 为
0022
文件的最大权限是 0666,而目录的最大权限是 0777, 那么当前用户的创建的目录权限就是 0755,对于当前用户而言就是 rwx-rx-rx 权限。而文件则是 0644,对于当前用户而言 rw-r-r 权限。所以如果没有重置掩码的话,那么对于目录而言就是 0755,而文件则是 0644 了。
注意
如果你在进程使用了 echo var_dump 等函数,一定要把标准输出等重定向到其他文件流中。新增加下面代码就可以了。
global $stdin, $stdout, $stderr;
$stdin = fopen(&#39;/dev/null&#39;, &#39;r&#39;);
$stdout = fopen(&#39;/www/php/txt.txt&#39;,&#39;wb&#39;);
$stderr = fopen(&#39;/dev/null&#39;, &#39;wb&#39;);
因为在上面已经关闭了标准输入输出,此时文件描述符 fd 已经没有,所有重新打开之后 fd 从非负开始依次是 0,1,2。正好作为标准输入输出的文件。当然重定向到那里需要你自己设置。
最后的二次 fork
这个问题需要好好斟酌,因为是非必须的。目前想不到有什么场景下必须两次 Fork。
以上就是PHP 实现守护进程的详细内容,更多请关注 第一PHP社区 其它相关文章!