1

我正在研究并尝试使用 php 执行守护进程,我发现自己不得不重新编译 PHP 以启用 PCNTL。然后我开始做一些测试。我分叉了单个孤儿示例:

#!/usr/bin/env php
<?php
$pid = pcntl_fork();

if ($pid === -1) {
    echo("Could not fork! \n");die;
} elseif ($pid) {
    echo("shell root tree \n");
} else {
    echo "Child process \n";

    chdir("/");

        fclose(STDIN);
        fclose(STDOUT);
    fclose(STDERR);
    $STDIN = fopen('/dev/null.txt', 'r');
    $STDOUT = fopen('/dev/null.txt', 'wb');
    $STDERR = fopen('/dev/null.txt', 'wb');

    posix_setsid();
    while(1) {
        echo ".";
        sleep(1);
    }
}

然后我运行了脚本:

$cd /var/www
$./test.php

一切进展顺利,文件 /dev/null.txt 被清除,并且每 1 秒在无限循环中更新。

然后我想知道 PCNTL 的好处,所以我更改了代码:

#!/usr/bin/env php
<?php

fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);

$STDIN = fopen('/dev/null.txt', 'r');
$STDOUT = fopen('/dev/null.txt', 'wb');
$STDERR = fopen('/dev/null.txt', 'wb');

while(1) {
    echo ".";
    sleep(1);
}

前面的两个例子都给了我相同的结果。我错过了什么吗?你能指导我吗

4

1 回答 1

0

您的两个示例都基本相同,除了第一个在继续之前分叉。分叉是进程在 UNIX 或衍生版本中成为守护进程的方式。

由于分叉使父进程和子进程共享相同的 STDIN STDOUT 和 STDERR 描述符,因此通常像您一样关闭它们。

在您的简单示例中,分叉没有任何意义。因为你fopen()3 次并且当时没有打开其他描述符,所以这些成为新的描述符 0、1 和 2,匹配输入、输出和错误,因此你echo ".";最终在那个文件中。

此外,/dev/null.txt它只是一个像这样命名的常规文件,而不是特殊的/dev/null空设备。

于 2021-01-14T21:32:48.527 回答