我正在尝试在php-fpm中使用pcntl_fork(),但它不可用,并且我得到了:

Call to undefined function pcntl_fork()

即使我已经在disable_functions中注释掉了php.iniphpinfo()显示作者,并且php -m也列出pcntl。如果我从cli执行脚本,则可以正常工作。我还需要启用其他选项吗?

作为MWE,我已经在https://github.com/white-gecko/pcntl-mwe resp中准备了一个最小的docker环境。
docker pull whitegecko/pcntl-mwe

如果您使用docker run -it --rm --name pcntl -p 8080:80 pcntl运行它,您将在http://localhost:8080/和phpinfo的示例http://localhost:8080/phpinfo.php处找到该示例。它是一个debian的jessie系统。

最佳答案

PCNTL扩展只限于在CLI中运行;您不能在其他服务器环境(fpm,mod_php等)中使用它。

应该发生的是,仅将标记为“cli”的扩展名静态链接到CLI二进制文件,或者允许在CLI中加载共享,而在针对其他SAPI(libphp7.so)的共享版本中则省略了这些扩展。

配置用于PHP的PCNTL的autoconf(ext/pcntl/config.m4)文件应该指示构建过程禁止在其他SAPIS中加载PCNTL,因此发生1)它不是很好,2)这不是将FPM合并到PHP中时考虑了这一点:因此FPM会忽略它并始终与PCNTL源链接(如果在编译时启用了扩展名),并且其他共享库由于共享DSO(共享)而允许您加载该库(如果已共享)库)本身并不强制执行SAPI限制。这些内容(FPM链接和其他加载)均不允许,并且强制不支持的SAPI加载PCNTL是一个糟糕的主意。

派生一个进程时,您将创建一个名为fork的进程的写时复制克隆:在Apache或FPM内部,这意味着您可能无法在子进程中正常管理重复的文件(套接字)句柄(因为您没有从PHP访问它们)。

应该将其限制为CLI(和早期CGI)的原因是,这些SAPI使用单个流程模型。尽管从技术上讲FPM是CGI接口(interface),但它肯定不是一个单一的过程,因此永远不会是在用户土地上进行 fork 的合适环境。

09-25 17:17