我试图在php fpm中使用pcntl_fork(),但它不可用,我得到:Call to undefined function pcntl_fork()
即使我已经在disable_functions中注释了php.ini。phpinfo()显示作者,php -m还列出pcntl。如果我是从cli执行脚本,它就会工作。是否需要启用其他选项?
作为MWE,我准备了一个最小的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)文件应该指示构建过程不允许在其他sapi中加载pcntl,因此1)它不是很好,2)当fpm合并到php时没有考虑到这一点:因此fpm忽略它,l无论如何都与pcntl源链接(如果在编译时启用了扩展),如果库是共享的,则其他sapi将允许您加载该库,因为dso(共享库)本身不强制sapi限制。这两件事(fpm链接和其他加载)都不应该被允许,强迫不受支持的sapi加载pcntl是一个糟糕的主意。
当您分叉一个进程时,您将创建一个名为fork:inside of apache或fpm的进程的copy-on-write克隆,这意味着复制的文件(socket)句柄可能无法在子进程中正常管理(因为您无法从php访问它们)。
这应该仅限于cli(和早期的cgi)的原因是,这些sapi使用单个进程模型。虽然fpm在技术上是一个cgi接口,但它肯定不是一个单一的进程,因此永远不会是一个适合在用户区分叉的环境。