iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > PHP编程 >PHP实现守护进程的示例代码
  • 579
分享到

PHP实现守护进程的示例代码

2024-04-02 19:04:59 579人浏览 八月长安
摘要

目录前言成为守护进程的步骤实现说明创建子进程并退出父进程创建新的会话重设文件掩码改变工作目录关闭标准输入输出其他注意事项前言 写 PHP CLI 程序的老司机们可能经常会写一些常驻进

前言

PHP CLI 程序的老司机们可能经常会写一些常驻进程,比如消息队列消费者进程,这些进程会一直运行,除非要发版,不然一般不会重启的,所以程序程序是不可能由我们通过 ssh 登录到服务器上通过终端来直接启动的(因为一旦断开 ssh 进程就退出了),常见的做法就是用 systemd 或者 supervisor 来使其成为 守护进程,这样进程就可以一直运行,遇到错误意外退出也能被自动重启。

好学的你可能会思考守护进程到底是怎么实现的?为什么有的程序既可以自己就成为守护进程,又可以通过 systemd 来后台运行?如果不依赖外部,我们的 php 程序该怎样变成守护进程呢?

成为守护进程的步骤

其实只需要创建子进程并退出父进程,将要处理的工作在子进程中进行就可以实现一个守护进程了。但是仅仅是这么做的话,如果后续任务很复杂,或者引入了一些第三方包,那么可能就会出现奇奇怪怪的问题了。

而在《UNIX环境高级编程》(英语:Advanced Programming in the UNIX Environment,简称APUE)一书中有介绍关于守护进程的编码规范,我们按照规范来实现我们的守护进程就可以避免出现那些奇怪的问题了。而且规范也不复杂,只需要几步就可以了:

  • 创建子进程,退出父进程
  • 子进程创建一个新的会话并成为 session leader
  • 重设文件掩码
  • 改变工作目录
  • 关闭标准输入输出

实现

<?php

function daemon()
{
    // [1] 创建子进程
    $pid = pcntl_fork();
    if ($pid == -1) {
        die('fork failed');
    }

    // [2] 如果是父进程,则退出
    if ($pid > 0) {
        exit(0);
    }

    ///////////////// 以下是子进程 /////////////////

    // [3] 创建一个新的会话并成为 session leader
    if ( ($sid = posix_setsid()) <= 0 ) {
        die("Set sid failed.\n");
    }

    // [4] 重设文件掩码
    umask(0);

    // [5] 改变工作目录
    if (chdir('/') === false) {
        die("chdir failed.\n");
    }

    // [6] 关闭标准输入输出
    fclose(STDIN);
    fclose(STDOUT);
    fclose(STDERR);
}

daemon();

// ... 真正的处理逻辑

说明

上面短短的十几二十行代码就实现了一个守护进程,接下来解释一下有些步骤为什么要这么做。

创建子进程并退出父进程

pcntl_fork() 的返回值有三种情况,上面的代码([1]和[2])已经处理了对应的情况。

创建新的会话

调用 posix_setsid() 创建新会话会使得当前进程成为新会话中的“会话首进程”,同时也会使当前进程成为“进程组组长”,并且使得当前进程脱离控制终端。

重设文件掩码

调用 umask() 重设文件掩码,这里通常是 0。为什么是 0 而不是其他呢,因为子进程从父进程继承来的文件掩码可能会屏蔽某些特定的文件操作权限。比如说引入的第三方库可能需要用特定的权限来创建文件,并且它没有将文件权限作为一个选项参数由你指定,那么就可能会出现失败的情况;而我们传入 0,会使得从调用了 umask() 之后,守护进程创建的文件权限为 0666,目录权限为 0777,均为最高权限。

关于 umask() 后面会展开新的篇幅来说明,感兴趣的可以先自行搜索资料学习

改变工作目录

通过 chdir() 我们将工作目录设置为根目录 /,主要是因为守护进程是长时间运行的,通常只有系统关闭/重启才会退出。假如从父进程继承来的工作目录是个挂载的文件系统,如果不改变工作目录,那么将会导致这个挂载的文件系统一直没法卸载。

当然也不一定要将工作目录切换到根目录,你也可以根据实际情况切换到特定的目录。

关闭标准输入输出

因为守护进程是脱离终端控制的,所以是没有标准输入输出交互的,我们将其关闭即可。

其他

二次 fork

你可能在一些资料中看到有人推荐你在 [3] 创建一个新的会话并成为 session leader 之后再次进行 fork。这一步骤是在基于 System V 的系统中,可以保证你的守护进程不是“会话首进程”,可以阻止其重新申请获取一个控制终端。

关闭不必要的文件描述符

按照编码规范,实际还有一步是关闭不必要的文件描述符。但我们为了简单起见,上面的代码在进程启动之后先创建守护进程再执行其他操作,因此这里只打开了三个文件描述符: 01 和 2(即标准输入、标准输出、标准错误)。

注意事项

因为上面的代码将标准输入输出关闭了,也就是说如果你在 daemon() 之后有诸如 echo "Hello world"; 之类的输出,那么你的程序将会出错然后退出,并且你将看不到任何错误信息(因为标准错误也被关闭了)。

解决方案有两种,一种是用 file_put_contents 代替 echo,但是这样并不优雅,而且万一引入的第三方包中写了 echo 或者是 file_put_contents(STDOUT, ...),那你的程序也会“莫名其妙”就挂了,会让你排查半天到底是哪里出了问题。

因此我们还可以在第[6]之后加入:

// [7] 重定向输入输出
    global $stdin, $stdout, $stderr;
    $stdin = fopen('/dev/null', 'r');
    $stdout = fopen('/dev/null', 'wb'); // 你也可以将标准输出重定向到指定的文件,相当于是日志
    $stderr = fopen('/dev/null', 'wb'); // 同上

到此这篇关于PHP实现守护进程的示例代码的文章就介绍到这了,更多相关PHP守护进程内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: PHP实现守护进程的示例代码

本文链接: https://www.lsjlt.com/news/148541.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • PHP实现守护进程的示例代码
    目录前言成为守护进程的步骤实现说明创建子进程并退出父进程创建新的会话重设文件掩码改变工作目录关闭标准输入输出其他注意事项前言 写 PHP CLI 程序的老司机们可能经常会写一些常驻进...
    99+
    2024-04-02
  • PHP怎么实现守护进程
    今天小编给大家分享一下PHP怎么实现守护进程的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。成为守护进程的步骤其实只需要创建子...
    99+
    2023-06-30
  • Python守护进程daemon实现
    1.1 守护进程 守护进程是系统中生存期较长的一种进程,常常在系统引导装入时启动,在系统关闭时终止,没有控制终端,在后台运行。守护进程脱离于终端是为了避免进程在执行过程中的信息在任何终端上显示并且进程也不会被任何终端所产生的终端信息...
    99+
    2023-01-31
    进程 Python daemon
  • Python实现Daemon(守护)进程
    最近在写Daemon进程,在编写过程中遇到一些小麻烦,最终还是解决了。 我编写了两种,第一种是编写了一个程序,将其用setsid命令让其放入后台运行,第二种是直接fork()一个进程,在代码里将进程设置为后台启动。 在os.sytem()...
    99+
    2023-01-31
    进程 Python Daemon
  • linux下的守护进程实例分析
    本篇内容主要讲解“linux下的守护进程实例分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“linux下的守护进程实例分析”吧!shell控制的php常驻进程...
    99+
    2024-04-02
  • python中的daemon守护进程实现
    守护进程是生存期长的一种进程。它们独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件。他们常常在系统引导装入时启动,在系统关闭时终止。 ...
    99+
    2023-01-31
    进程 python daemon
  • C#守护进程如何实现
    今天小编给大家分享一下C#守护进程如何实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。1、为什么需要守护进程一般是为了保护...
    99+
    2023-07-02
  • python守护进程监控子进程怎么实现
    在Python中,可以使用multiprocessing模块来创建子进程并监控它们。具体实现方法如下: 导入multiproces...
    99+
    2023-10-23
    python
  • php万字码出完美守护进程详解
    目录前事提要基本概念基本特点创建守护进程要求前事提要 上期我们详细学习了会话的概念以及用法,会话,进程组,终端的理解对本篇讲述的守护进程极其重要,如还不理解相关概念建议翻看我往期关于...
    99+
    2024-04-02
  • C#实现对文件进行加密保护的示例代码
    目录实践过程效果代码实践过程 效果 代码 public partial class Form1 : Form { public Form1() { ...
    99+
    2022-12-31
    C#实现文件加密 C#文件加密 C# 加密
  • 如何进行Python进程的守护进程实施
    如何进行Python进程的守护进程实施,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。Python进程这一计算机语言在实际的应用中,如果你在实际应用的过程中遇到相...
    99+
    2023-06-17
  • C# 守护进程的介绍及实现详解
    目录1、为什么需要守护进程2、守护进程有哪几种方式3、监听系统事件 和 WMI查询事件代码实现1) 系统事件监听进程的关闭2)WMI监听进程的启动和关闭1、为什么需要守护进程 一般是...
    99+
    2024-04-02
  • Android AIDL实现跨进程通信的示例代码
    AIDL是Android接口定义语言,它可以用于让某个Service与多个应用程序组件之间进行跨进程通信,从而可以实现多个应用程序共享同一个Service的功能。实现步骤例:用 A程序去访问 B程序的MyService.java服务 在B...
    99+
    2023-05-30
    android 跨进程通信 aidl
  • SAP ABAP守护进程的实现方式是什么
    本篇文章给大家分享的是有关SAP ABAP守护进程的实现方式是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。Linux系统很多服务都通过守护进程实现,常见的守护进程有系统日...
    99+
    2023-06-03
  • 如何使linux shell实现守护进程脚本
    这篇文章主要讲解了“如何使linux shell实现守护进程脚本”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何使linux shell实现守护进程脚本”吧!#! /bin/sh...
    99+
    2023-06-09
  • python实现进制转化的示例代码
    做题思路 (1)掌握十进制转化为其他进制的方法 (2)分析和解决如何将整数和小数分离,以及他们的存储方式。(3)如何设计python函数去实现它们 (4)了解辗转相除法和列表如何运用...
    99+
    2024-04-02
  • 如何编写用模板的方式创建守护进程代码
    这篇文章主要介绍“如何编写用模板的方式创建守护进程代码”,在日常操作中,相信很多人在如何编写用模板的方式创建守护进程代码问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何编写用模板的方式创建守护进程代码”的疑...
    99+
    2023-06-09
  • Java并发中守护线程的示例分析
    今天就跟大家聊聊有关Java并发中守护线程的示例分析,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。在Java中有两类线程:用户线程 (User Thread)、守护线程 (Daemo...
    99+
    2023-06-17
  • PHP实现生成二维码的示例代码
    目录前言1、目前有2种类型的二维码2、用户扫描带场景值二维码时,可能推送以下两种事件3、创建二维码ticket4、临时二维码请求说明5、永久二维码请求说明6、临时二维码和永久二维码生...
    99+
    2024-04-02
  • 在Dockerfile的RUN指令中不执行守护进程的示例分析
    小编给大家分享一下在Dockerfile的RUN指令中不执行守护进程的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!不要在你的Dockerfile中的RUN指令中执行守护进程 $ cat&nbs...
    99+
    2023-06-04
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作