如何正确的使php进程以守护进程方式运行

守护进程是一个在后台运行并且不受任何终端控制的进程。 关于守护进程的详细解释可以看看百度百科

下面我们看看php的脚本程序怎么作为守护进程运行在后台。

在Linux中 , 大概有三种方式实现脚本后台化 :

  • 1.在命令后添加一个&符号,比如 php task.php &。这个方法的缺点在于:如果终端关闭,无论是正常关闭还是非正常关闭,这个php进程都会随着终端关闭而关闭;其次是代码中如果有echo或者var_dump()之类的输出文本,会被输出到当前的终端窗口中。
  • 2.使用nohup命令,比如nohup php task.php &。默认情况下,代码中echo或者var_dump之类输出的文本会被输出到php代码同级目录的nohup.out文件中。如果你关闭终端,该进程不会被关闭,依然会在后台持续运行。但是如果终端遇到异常退出或者终止,该php进程也会随即退出。本质上 也并非稳定可靠的守护进程方案 。
  • 3.使用forksetsid,这个方案在上面百度百科中也有详细介绍,我们这里以php代码来演示:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    <?php
    // deamon.php

    umask(0); //把文件掩码清0

    // 一次fork
    $pid = pcntl_fork();
    if ($pid < 0) {
    exit(' fork出错 ');
    } else if ($pid > 0) {
    exit(' 父进程退出 '); // 父进程退出,子进程变成孤儿进程被1号进程收养,进程脱离终端
    }

    // 将当前子进程提升会会话组组长 这是至关重要的一步
    if (!posix_setsid()) {
    exit(' setsid 出错 ');
    }

    //修改当前进程的工作目录,由于子进程会继承父进程的工作目录,修改工作目录以释放对父进程工作目录的占用。
    chdir('/tmp');

    // 二次fork
    // 通过上一步,我们创建了一个新的会话组长,进程组长,且脱离了终端,但是会话组长可以申请重新打开一个终端,为了避免
    // 这种情况,我们再次创建一个子进程,并退出当前进程,这样运行的进程就不再是会话组长。
    $pid = pcntl_fork();
    if ($pid < 0) {
    exit(' fork 出错 ');
    } else if ($pid > 0) {
    exit(' 父进程退出 ');
    }

    //由于守护进程用不到标准输入输出,关闭标准输入,输出,错误输出描述符
    fclose(STDIN);
    fclose(STDOUT);
    fclose(STDERR);

    // 真正的逻辑代码们 下面仅仅写个循环以示例
    for ($i = 1; $i <= 100; $i++) {
    sleep(1);
    file_put_contents('daemon.log', $i, FILE_APPEND);
    }
    ```

    运行看看效果吧
    ```sh
    php deamon.php
    tail -f daemon.log

另外还有一种运行脚本的方式也值得一提:利用 screen / tmux 等软件,将脚本运行在可以在一个虚拟终端之上。

参考:

打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!

请我喝杯咖啡吧~

支付宝
微信