如何确定PHP-FPM进程中正在执行哪个脚本

32
我正在运行nginx+php-fpm。有没有办法知道每个PHP进程在做什么?类似于apache中的扩展mod_status,我可以看到PID为x的apache进程正在处理URL y。我不确定PHP进程是否知道URL,但获取脚本路径和名称就足够了。
4个回答

36
在经过几个小时的谷歌搜索和浏览PHP.net的错误跟踪系统后,我找到了解决方案。该解决方案自PHP 5.3.8或5.3.9以来就可用,但似乎没有记录。基于功能请求#54577,状态页面支持选项full,它将分别显示每个工作进程的状态。因此,例如URL将是http://server.com/php-status?full,示例输出如下:
pid:                  22816
state:                Idle
start time:           22/Feb/2013:15:03:42 +0100
start since:          10933
requests:             28352
request duration:     1392
request method:       GET
request URI:          /ad.php?zID=597
content length:       0
user:                 -
script:               /home/web/server.com/ad/ad.php
last request cpu:     718.39
last request memory:  1310720

我该如何访问它?我需要在nginx配置中添加任何参数吗? - babak faghihian
@babakfaghihian 是的,你需要将那个URL(例如/php-status)传递给php-fpm。 - Marki555
6
很抱歉,如果你的PHP应用程序使用URL重写(也称为“友好的URL”),大多数MVC框架都会这样做,那么请求URI将始终显示为/index.php。实际的URL是通过REQUEST_URI环境变量传递的,该变量不会显示在状态输出中。 - Glenn Schmidt
@Marki555:老兄,你真是救了我的命啊!我一直在追踪一些在我的php-fpm容器上消耗内存的脚本,但是用我找到的所有方法都没有成功... 直到这个 http://server.com/php-status?full 。那个"?full"参数就像一盏明灯,向我展示了我一直在寻找的有问题的URI/脚本。非常感谢你! - Giorgiolino

15

PHP-FPM内置状态监视器,但它不像mod_status那样详细。从php-fpm配置文件/etc/php-fpm.d/www.conf(在CentOS 6上)中可以找到。

; The URI to view the FPM status page. If this value is not set, no URI will be
; recognized as a status page. By default, the status page shows the following
; information:
;   accepted conn    - the number of request accepted by the pool;
;   pool             - the name of the pool;
;   process manager  - static or dynamic;
;   idle processes   - the number of idle processes;
;   active processes - the number of active processes;
;   total processes  - the number of idle + active processes.
; The values of 'idle processes', 'active processes' and 'total processes' are
; updated each second. The value of 'accepted conn' is updated in real time.
; Example output:
;   accepted conn:   12073
;   pool:             www
;   process manager:  static
;   idle processes:   35
;   active processes: 65
;   total processes:  100
; By default the status page output is formatted as text/plain. Passing either
; 'html' or 'json' as a query string will return the corresponding output
; syntax. Example:
;   http://www.foo.bar/status
;   http://www.foo.bar/status?json
;   http://www.foo.bar/status?html
; Note: The value must start with a leading slash (/). The value can be
;       anything, but it may not be a good idea to use the .php extension or it
;       may conflict with a real PHP file.
; Default Value: not set
;pm.status_path = /status

如果您启用此选项,您可以将路径从nginx传递到PHP-FPM的套接字/端口,以便您可以查看状态页面。

nginx.conf:

location /status {

    include fastcgi_params;
    fastcgi_pass unix:/var/lib/php/php-fpm.sock;

}

是的,我知道php-fpm中的这个状态,我已经在munin和zabbix监控中使用它了。但是它只提供聚合信息,而不是每个进程的信息。 - Marki555
除了创建自定义日志解决方案或设置访问日志处理之外,我认为你没有太多其他选择,但这并不能提供您所需的详细信息,例如处理时间。我相信随着PHP-FPM的成熟,他们将扩展状态报告。 - sjdaws
1
最后我发现状态页面支持每个进程的信息(请参见我的答案)。 - Marki555
开发人员将调试信息放在这样的路径上,真是个可怕的想法。如果你要这样做,请确保URL受到限制。 - toraman

7

cgi命令行更方便:

SCRIPT_NAME=/status \
SCRIPT_FILENAME=/status \
REQUEST_METHOD=GET \
cgi-fcgi -bind -connect 127.0.0.1:9000

5
请注意,您必须添加 QUERY_STRING=full 才能返回 OP 寻找的内容。将 SCRIPT_FILENAME 更改为 /status?full 是行不通的。 - Isius
1
您仍需要取消注释 pm.status_path 以启用状态页面;此方法的优点是无需通过 Web 服务器公开。SCRIPT_NAMESCRIPT_FILENAME 应与 php-fpm.conf 文件中的 pm.status_path 相同。最后一个参数 (127.0.0.1:9000) 是连接到 FCGI 服务器,而不是 Web 服务器--它应该是同一 INI 文件中 listen 参数的内容。如果它是一个套接字,您可能需要使用 sudo 进行连接,在这种情况下还要使用 -E 告诉 sudo 将环境变量传递给 cgi-fcgi - Wolfgang

0

你可以使用strace实时显示脚本的运行情况,以及许多其他信息。它非常冗长,但可以给你一个很好的整体了解正在发生的事情:

# switch php-fpm7.0 for process you're using
sudo strace -f $(pidof php-fpm7.0 | sed 's/\([0-9]*\)/\-p \1/g')

以上内容将附加到 php fpm 的分叉进程上。使用-p来附加到特定的 pid。

以上将获取脚本路径。要获取 URL,请查看您的 nginx / apache 访问日志。

顺便提一下,要查看系统调用和哪些调用需要最长时间:

sudo strace -c -f $(pidof php-fpm7.0 | sed 's/\([0-9]*\)/\-p \1/g')

等待一段时间,然后按下Ctrl-C键


2
这个命令可以工作:strace -f $(pidof php-fpm | sed 's/\([0-9]*\)/\-p \1/g') - Sos.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接