如何在nginx/php fpm环境中正确地进行fork?

如何在nginx/php fpm环境中正确地进行fork?,nginx,fork,php,Nginx,Fork,Php,我有一个在我的机器上运行的非常简单的php套接字服务器。我用简单的方法创建了一个convience类,如“restart”和“stop”等,以便在服务器运行后控制它 restart函数的作用是向服务器发送停止命令,然后在父进程返回调用方的同时,分叉进程并在子进程内启动套接字服务器的新实例 这在命令行上非常有效,但是我正在尝试创建一个管理网页,该网页会重新启动套接字服务器,而分叉会导致php fpm出现问题。基本上,当父进程结束时,“页面加载”的生命并没有结束,nginx/php fpm在分叉进程

我有一个在我的机器上运行的非常简单的php套接字服务器。我用简单的方法创建了一个convience类,如“restart”和“stop”等,以便在服务器运行后控制它

restart函数的作用是向服务器发送停止命令,然后在父进程返回调用方的同时,分叉进程并在子进程内启动套接字服务器的新实例

这在命令行上非常有效,但是我正在尝试创建一个管理网页,该网页会重新启动套接字服务器,而分叉会导致php fpm出现问题。基本上,当父进程结束时,“页面加载”的生命并没有结束,nginx/php fpm在分叉进程也结束之前不会将进程重新分配给新的连接

在我的例子中,我不希望分叉过程永远结束,我最终得到的是一个完全衰弱的服务器。(在我的测试环境中,为了简单起见,我将工作池设置为仅1,在生产环境中这将更高,但此问题将导致一个工作槽被永久占用)

我尝试了一些方法,包括在分叉之前调用
fastcgi\u finish\u request()
,但是这没有任何影响


如何从php fpm工作进程重新启动服务而不锁定nginx连接池中的分配?

听起来您的协议设计有误。服务器应该能够重新启动自身。在互联网上有很多这样做的例子。 客户端(您的网页)不需要进行任何分叉。
服务器也不应该在php fpm内部运行,而是一个控制台应用程序,它使用守护程序(3)类型的接口将自身从控制台分离

解决方案简单而基本

子进程不重定向STDUT和STDRR到/DEV/NULL,因此即使父进程完成,子进程仍然具有活动文件描述符的事实导致PHP FPM考虑其池中的连接仍然处于活动状态,因此,它永远不会被重新分配给新的连接,因为子进程将持续运行

将STDERR和STDOUT重定向到/dev/null会导致php fpm正确地重新分配连接,同时允许子进程(套接字服务器)永远运行。案件结案

./some/command >/dev/null 2>&1
应该在一英里外看到这个


(我几个月前就解决了这个问题,但很长时间没有登录到这个帐户……我用了7个月的时间才发现我需要将输出指向/dev/null!)

我不太明白这与php-fpm有什么关系。我假设您使用TCP连接到服务器,然后发送重新启动命令。如果您在分叉之前发送关闭消息,这应该没有问题。我有一个运行的套接字文件服务器。我还有一个运行的nginx/php fpm服务器。我有一个网页,它向套接字文件服务器发送一个停止命令,然后从子进程派生并启动一个新的套接字文件服务器。然后,父进程退出,但php fpm似乎没有重新分配连接,因为子进程仍在运行。嘿,如果按我的方式,我们就不会有任何这些愚蠢的web界面来管理守护进程控制。我在命令行上通过/etc/init.d或任何与非init.d脚本相关的命令来执行此操作。这对我来说很好,但对老板来说不是。他想要一个闪亮的重启按钮,但实际上他并没有使用这个按钮,因为当他想要重启服务器时,他让我去做,我在命令行上做。。。。无论如何,我找到了我的解决方案,贴在下面的答案中。作为背景,我编写的socket服务器已经完成,web界面方面是一个事后考虑的问题。啊,是的,我在3年前将BSD的守护程序作为pcntl扩展的一部分实现到php中,这样我就可以分叉并关闭stdin/stdout了。在php本身中无法做到这一点(至少在当时),因为您得到了重复的stdin/stdout,而不是实际的stdin/stdout。