欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

有关PHP的DEBUG一点想法

程序员文章站 2022-04-11 10:30:14
...

环境构建

# 创建网络[默认bridge]
docker network create nginx-php 

# 创建php容器
docker run -d -p 9000:9000 -v E:\MonkeyCode\local\php:/data/projects --name dev-php-v7.3 --network nginx-php php:7.3-fpm-alpine

# 创建nginx容器
docker run -d -p 8000-8080:8000-8080 -v E:\MonkeyCode\local\php:/data/projects --name dev-nginx-latest --network nginx-php nginx:latest
# nginx配置nginx注意事项
1. 在location节点外定义项目根目录;
2. 调整变量 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name
3. 注意核对 fastcgi_pass php-ip:port[fpm]

PHP安装XDebug扩展

wget https://pecl.php.net/get/xdebug-3.0.4.tgz
tar -zxf xdebug-3.0.4.tgz
docker-php-source extract
mv xdebug-3.0.4 /usr/src/php/etc/xdebug
docker-php-ext-install xdebug

# 查看扩展
php --ri xdebug

调整XDebug配置

; vi /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini

zend_extension="xdebug.so"
xdebug.mode=debug
xdebug.start_with_request=yes
xdebug.client_host=host.docker.internal
xdebug.client_port=9001
xdebug.idekey=www

; 配置参考 https://xdebug.org/docs/all_settings

调整IDE配置

File => Settings => PHP => Debug
Xdebug port 和 xdebug.client_port保持一致即可

File => Settings => PHP => Server
Add Server
host 站点(ip/域名) port 站点端口 Debugger XDebug
# 我这里是docker, 必须要配置路径映射
file://E:/MonkeyCode/local/php/test => /data/projects/test[这是项目在容器中绝对路径]

设置 run/debug configurations
添加一个 php-remote-debug, IDE key 和 xdebug.idekey保持一致即可
然后 start listenings 就类似电话那个icon, 点击**
最后 run/debug 即可

访问项目时, 地址加上XDEBUG_SESSION_START=idekey[我这里配置的www]

原理分析

为分析 XDebugPHP 的行为, 先来看下关闭 Debug 下表现, 为了调试方便, 我们先将 php-fpmwork proccess 调整为一个, 主要修改 /usr/local/php/73/etc/php-fpm.d/www.conf 的如下配置:

pm = static
pm.max_children = 1
; 保存后, 重启php-fpm, 我这里使用sudo systemctl restart php-fpm73即可
; 可使用 ps aux|grep php-fpm|grep -v color|grep -v master|wc -l 验证, 应输出1

这里还要补充一个命令strace , 能够记录和解析进程的系统调用以及接收到的信号值, 更多可参考 strace官网.

Debug 模式

xdebug.mode = off

大致流程: 请求进入创建fd => 读取数据 => 解析目标 => 执行(暂时没有看到) => 输出数据 => 关闭fd => 等待下轮请求.

sudo strace -tt -T -v -s 1024 -p 4856
# -tt 在每行输出的前面, 显示毫秒级别的时间
# -T 显示每次系统调用所花费的时间
# -v 对于某些相关调用, 把完整的环境变量, 文件stat结构等输出
# -s 当系统调用的某个参数是字符串时, 最多输出指定长度的内容, 默认32个字节
# 指定要跟踪的进程pid, 这里的4856, 是当前机器的php-fpm work proccess的进程id
strace: Process 4856 attached
09:08:15.298419 accept(8,
# SOCKET accept(int sockfd[套接字描述符], struct sockaddr *addr, socklen_t *addrlen);

打开浏览器键入 http://127.0.0.1:85/index.php , 监听响应如下:

09:08:15.298419 accept(8, {sa_family=AF_UNIX}, [112->2]) = 3 <157.450188>
# 请求进入, 创建对应fd
09:10:52.749787 poll([{fd=3, events=POLLIN}], 1, 5000) = 1 ([{fd=3, revents=POLLIN}]) <0.000037>
# 监听fd, 等待响应
09:10:52.750053 times({tms_utime=0, tms_stime=0, tms_cutime=0, tms_cstime=0}) = 1718163427 <0.000117>
# 初始时间标记
09:10:52.750407 read(3, "\1\1\0\1\0\10\0\0", 8) = 8 <0.000119>
# 从fd读取8字节数据, 疑似cgi标记头参数
09:10:52.750793 read(3, "\0\1\0\0\0\0\0\0", 8) = 8 <0.000083>
# 从fd读取8字节数据, 疑似cgi标记头参数
09:10:52.751079 read(3, "\1\4\0\1\4\330\0\0", 8) = 8 <0.000086>
# 从fd读取8字节数据, 疑似cgi标记头参数
09:10:52.751362 read(3, "\17/SCRIPT_FILENAME/home/speauty/PhpstormProjects/XDebug/index.php\t\0PATH_INFO\17%PATH_TRANSLATED/home/speauty/PhpstormProjects/XDebug\f\32QUERY_STRINGXDEBUG_SESSION_START=10503\16\3REQUEST_METHODGET\f\0CONTENT_TYPE\16\0CONTENT_LENGTH\v\nSCRIPT_NAME/index.php\v%REQUEST_URI/index.php?XDEBUG_SESSION_START=10503\f\nDOCUMENT_URI/index.php\r%DOCUMENT_ROOT/home/speauty/PhpstormProjects/XDebug\17\10SERVER_PROTOCOLHTTP/1.1\16\4REQUEST_SCHEMEhttp\21\7GATEWAY_INTERFACECGI/1.1\17\fSERVER_SOFTWAREnginx/1.18.0\v\tREMOTE_ADDR127.0.0.1\v\5REMOTE_PORT57778\v\tSERVER_ADDR127.0.0.1\v\2SERVER_PORT85\v\20SERVER_NAMEwww.xdebug.local\17\3REDIRECT_STATUS200\t\fHTTP_HOST127.0.0.1:85\17\nHTTP_CONNECTIONkeep-alive\22\tHTTP_CACHE_CONTROLmax-age=0\16(HTTP_SEC_CH_UA\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"90\"\25\2HTTP_SEC_CH_UA_MOBILE?0\36\1HTTP_UPGRADE_INSECURE_REQUESTS1\17iHTTP_USER_AGENTMozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36\v\200\0\0\207HTTP_ACCEPTtext/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,app"..., 1240) = 1240 <0.000060>
# 从fd读取1240字节数据, nginx通过cgi协议向cgi程序交流数据
09:10:52.751569 read(3, "\1\4\0\1\0\0\0\0", 8) = 8 <0.000029>
# 从fd读取8字节数据, 疑似cgi标记尾参数

09:10:52.751685 lstat("/home/speauty/PhpstormProjects/XDebug/index.php", {st_dev=makedev(0x8, 0x2), st_ino=11677842, st_mode=S_IFREG|0664, st_nlink=1, st_uid=1000, st_gid=1000, st_blksize=4096, st_blocks=8, st_size=39, st_atime=1621326231 /* 2021-05-18T16:23:51.886290838+0800 */, st_atime_nsec=886290838, st_mtime=1621326206 /* 2021-05-18T16:23:26.030695433+0800 */, st_mtime_nsec=30695433, st_ctime=1621326206 /* 2021-05-18T16:23:26.030695433+0800 */, st_ctime_nsec=30695433}) = 0 <0.000036>
09:10:52.751881 lstat("/home/speauty/PhpstormProjects/XDebug", {st_dev=makedev(0x8, 0x2), st_ino=11677764, st_mode=S_IFDIR|0775, st_nlink=3, st_uid=1000, st_gid=1000, st_blksize=4096, st_blocks=8, st_size=4096, st_atime=1621326208 /* 2021-05-18T16:23:28.278660231+0800 */, st_atime_nsec=278660231, st_mtime=1621326206 /* 2021-05-18T16:23:26.030695433+0800 */, st_mtime_nsec=30695433, st_ctime=1621326206 /* 2021-05-18T16:23:26.030695433+0800 */, st_ctime_nsec=30695433}) = 0 <0.000027>
09:10:52.752030 lstat("/home/speauty/PhpstormProjects", {st_dev=makedev(0x8, 0x2), st_ino=11535344, st_mode=S_IFDIR|0775, st_nlink=4, st_uid=1000, st_gid=1000, st_blksize=4096, st_blocks=8, st_size=4096, st_atime=1621305495 /* 2021-05-18T10:38:15.129185253+0800 */, st_atime_nsec=129185253, st_mtime=1621325497 /* 2021-05-18T16:11:37.726187251+0800 */, st_mtime_nsec=726187251, st_ctime=1621325497 /* 2021-05-18T16:11:37.726187251+0800 */, st_ctime_nsec=726187251}) = 0 <0.000026>09:10:52.752173 lstat("/home/speauty", {st_dev=makedev(0x8, 0x2), st_ino=11539164, st_mode=S_IFDIR|0755, st_nlink=55, st_uid=1000, st_gid=1000, st_blksize=4096, st_blocks=8, st_size=4096, st_atime=1621384607 /* 2021-05-19T08:36:47.192934664+0800 */, st_atime_nsec=192934664, st_mtime=1621385072 /* 2021-05-19T08:44:32.371170591+0800 */, st_mtime_nsec=371170591, st_ctime=1621385072 /* 2021-05-19T08:44:32.371170591+0800 */, st_ctime_nsec=371170591}) = 0 <0.000026>
09:10:52.752315 lstat("/home", {st_dev=makedev(0x8, 0x2), st_ino=11534337, st_mode=S_IFDIR|0755, st_nlink=3, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=8, st_size=4096, st_atime=1621298069 /* 2021-05-18T08:34:29.984991526+0800 */, st_atime_nsec=984991526, st_mtime=1606266613 /* 2020-11-25T09:10:13.970999772+0800 */, st_mtime_nsec=970999772, st_ctime=1606266613 /* 2020-11-25T09:10:13.970999772+0800 */, st_ctime_nsec=970999772}) = 0 <0.000026>
# 从目标文件到根目录直接子目录反向依次检测文件信息

09:10:52.752601 rt_sigaction(SIGPROF, NULL, {sa_handler=0x55ace118f290, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x7f8602fe5210}, 8) = 0 <0.000032>
# SIGPROF表示使用setitimer指定的Profiling Interval Timer所产生
# SA_RESTORER 使被信号打断的系统调用自动重新发起, 据说已废弃
# SA_SIGINFO 使用 sa_sigaction 成员而不是 sa_handler 作为信号处理函数
09:10:52.752834 rt_sigaction(SIGHUP, NULL, {sa_handler=0x55ace118f290, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x7f8602fe5210}, 8) = 0 <0.000025>
# SIGHUP 在用户结束终端连接时发出(关闭终端,断开ssh),系统对SIGHUP信号的默认处理是终止收到该信号的进程.所以若是程序中没有捕捉该信号,当收到该信号时,进程就会退出
09:10:52.752976 rt_sigaction(SIGINT, NULL, {sa_handler=0x55ace118f290, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x7f8602fe5210}, 8) = 0 <0.000025>
09:10:52.753095 rt_sigaction(SIGQUIT, NULL, {sa_handler=0x55ace118f290, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x7f8602fe5210}, 8) = 0 <0.000023>
09:10:52.753194 rt_sigaction(SIGTERM, NULL, {sa_handler=0x55ace118f290, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x7f8602fe5210}, 8) = 0 <0.000023>
09:10:52.753292 rt_sigaction(SIGUSR1, NULL, {sa_handler=0x55ace118f290, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x7f8602fe5210}, 8) = 0 <0.000023>
09:10:52.753655 rt_sigaction(SIGUSR2, NULL, {sa_handler=0x55ace118f290, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x7f8602fe5210}, 8) = 0 <0.000039>

09:10:52.753800 setitimer(ITIMER_PROF, {it_interval={tv_sec=0, tv_usec=0}, it_value={tv_sec=3600, tv_usec=0}}, NULL) = 0 <0.000144>

09:10:52.754098 rt_sigaction(SIGPROF, {sa_handler=0x55ace118f290, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x7f8602fe5210}, NULL, 8) = 0 <0.000028>
09:10:52.754253 rt_sigprocmask(SIG_UNBLOCK, [PROF], NULL, 8) = 0 <0.000025>

09:10:52.754445 openat(AT_FDCWD, "/home/speauty/PhpstormProjects/XDebug/index.php", O_RDONLY) = 4 <0.000054>
09:10:52.754600 fstat(4, {st_dev=makedev(0x8, 0x2), st_ino=11677842, st_mode=S_IFREG|0664, st_nlink=1, st_uid=1000, st_gid=1000, st_blksize=4096, st_blocks=8, st_size=39, st_atime=1621326231 /* 2021-05-18T16:23:51.886290838+0800 */, st_atime_nsec=886290838, st_mtime=1621326206 /* 2021-05-18T16:23:26.030695433+0800 */, st_mtime_nsec=30695433, st_ctime=1621326206 /* 2021-05-18T16:23:26.030695433+0800 */, st_ctime_nsec=30695433}) = 0 <0.000026>
09:10:52.754779 fstat(4, {st_dev=makedev(0x8, 0x2), st_ino=11677842, st_mode=S_IFREG|0664, st_nlink=1, st_uid=1000, st_gid=1000, st_blksize=4096, st_blocks=8, st_size=39, st_atime=1621326231 /* 2021-05-18T16:23:51.886290838+0800 */, st_atime_nsec=886290838, st_mtime=1621326206 /* 2021-05-18T16:23:26.030695433+0800 */, st_mtime_nsec=30695433, st_ctime=1621326206 /* 2021-05-18T16:23:26.030695433+0800 */, st_ctime_nsec=30695433}) = 0 <0.000025>
09:10:52.754937 fstat(4, {st_dev=makedev(0x8, 0x2), st_ino=11677842, st_mode=S_IFREG|0664, st_nlink=1, st_uid=1000, st_gid=1000, st_blksize=4096, st_blocks=8, st_size=39, st_atime=1621326231 /* 2021-05-18T16:23:51.886290838+0800 */, st_atime_nsec=886290838, st_mtime=1621326206 /* 2021-05-18T16:23:26.030695433+0800 */, st_mtime_nsec=30695433, st_ctime=1621326206 /* 2021-05-18T16:23:26.030695433+0800 */, st_ctime_nsec=30695433}) = 0 <0.000025>
09:10:52.755085 mmap(NULL, 39, PROT_READ, MAP_SHARED, 4, 0) = 0x7f8600000000 <0.000048>
09:10:52.755227 getcwd("/", 4095)       = 2 <0.000031>
09:10:52.755373 chdir("/home/speauty/PhpstormProjects/XDebug") = 0 <0.000026>
09:10:52.755535 munmap(0x7f8600000000, 39) = 0 <0.000038>
09:10:52.755642 close(4)                = 0 <0.000023>
09:10:52.755733 chdir("/")              = 0 <0.000022>
09:10:52.755823 times({tms_utime=0, tms_stime=0, tms_cutime=0, tms_cstime=0}) = 1718163428 <0.000020>
09:10:52.755911 write(2, "\0", 1)       = 1 <0.000021>
09:10:52.756032 setitimer(ITIMER_PROF, {it_interval={tv_sec=0, tv_usec=0}, it_value={tv_sec=0, tv_usec=0}}, NULL) = 0 <0.000020>
09:10:52.756153 write(3, "\1\6\0\1\0H\0\0X-Powered-By: PHP/7.3.25\r\nContent-type: text/html; charset=UTF-8\r\n\r\nx124\1\3\0\1\0\10\0\0\0\0\0\0\0\0\0\0", 96) = 96 <0.000126>
09:10:52.756369 shutdown(3, SHUT_WR)    = 0 <0.000048>
09:10:52.756517 recvfrom(3, "\1\5\0\1\0\0\0\0", 8, 0, NULL, NULL) = 8 <0.000162>
09:10:52.756869 recvfrom(3, "", 8, 0, NULL, NULL) = 0 <0.000073>
09:10:52.757039 close(3)                = 0 <0.000098>
09:10:52.757264 setitimer(ITIMER_PROF, {it_interval={tv_sec=0, tv_usec=0}, it_value={tv_sec=0, tv_usec=0}}, NULL) = 0 <0.000065>
09:10:52.757462 accept(8,


# 涉及函数原型
# int poll(struct pollfd fd[], nfds_t nfds, int timeout); 监视并等待多个文件描述符的属性变化
# ssize_t read(int fd, void *buf, size_t count[请求读取的字节数]); 从fd中读取buf, 并返回成功读取字节长度
# ssize_t write(int fd, const void *buf, size_t count); 成功返回写入的字节数, 出错返回-1
# int lstat(const char *path, struct stat *buf[返回文件的信息, 针对符号链接, 返回链接本身, 而不是而非目标文件]); 成功为0, 否则为-1
# clock_t times(struct tms *buf);
# int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); 检查并改变信号
# int openat(int dirfd, const char *pathname, int flags); 打开或创建一个文件

Debug 模式

xdebug.mode = debug

PHP => 客户端[ c ] ide[phpstorm] => 服务端[ s ]

大致流程: 连接 s => s 获取配置相关参数[例如 show_hidden 等] => sc 核对状态 => 进入断点 s 发送断点位置, c 响应, 并输出一些头参数和超全局变量 => 根据 s 发送的指令, 是否下一断点和退出( detach ).

就交互模型来说, 和常规 cs 无异, 只不过这里的相关指定从 s 发出, s 响应. 在配置上 xdebug.client_host 也还是有一定道理.

# 未打开 ide[phpstorm]
10:11:48.201559 connect(4, {sa_family=AF_INET, sin_port=htons(9003), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (操作现在正在进行) <0.000180>
10:11:48.201941 poll([{fd=4, events=POLLIN|POLLPRI|POLLOUT}], 1, 200) = 1 ([{fd=4, revents=POLLIN|POLLOUT|POLLERR|POLLHUP}]) <0.000079>
10:11:48.202186 close(4)                = 0 <0.000107>
10:11:48.202440 write(2, "NOTICE: PHP message: Xdebug: [Step Debug] Could not connect to debugging client. Tried: 127.0.0.1:9003 (through xdebug.client_host/xdebug.client_port) :-(\n", 155) = 155 <0.000043>
# 尝试连接 xdebug.client 失败, 为此, 还是要把ide打开, 至少有对应client
# 开启ide
# 浏览器访问 http://127.0.0.1/index.php?XDEBUG_SESSION_START=12456, 这个数字好像可以随便键入, 那边都可以进入断点过程
# 下面仅贴了部分终端输出, 基本上是非debug下没有的

# 连接debug客户端
10:26:28.812154 socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 4 <0.000057>
# ...
10:26:28.812465 connect(4, {sa_family=AF_INET, sin_port=htons(9003), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (操作现在正在进行) <0.000176>
# ...
10:26:28.813977 getpid()                = 6992 <0.000023>
10:26:28.814080 write(4, "510\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<init xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" fileuri=\"file:///home/speauty/PhpstormProjects/XDebug/index.php\" language=\"PHP\" xdebug:language_version=\"7.3.25\" protocol_version=\"1.0\" appid=\"6992\" idekey=\"1543\"><engine version=\"3.0.4\"><![CDATA[Xdebug]]></engine><author><![CDATA[Derick Rethans]]></author><url><![CDATA[https://xdebug.org]]></url><copyright><![CDATA[Copyright (c) 2002-2021 by Derick Rethans]]></copyright></init>\0", 515) = 515 <0.000115>
10:26:28.814395 getpid()                = 6992 <0.000072>

# 设置参数 show_hidden?
10:26:28.814628 recvfrom(4, "feature_set -i 1 -n show_hidden -v 1\0", 128, 0, NULL, NULL) = 37 <0.006103>
10:26:28.821038 write(4, "219\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<response xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" command=\"feature_set\" transaction_id=\"1\" feature=\"show_hidden\" success=\"1\"></response>\0", 224) = 224 <0.000183>
10:26:28.821476 recvfrom(4, "feature_set -i 2 -n max_depth -v 1\0", 128, 0, NULL, NULL) = 35 <0.001402>
10:26:28.823115 write(4, "217\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<response xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" command=\"feature_set\" transaction_id=\"2\" feature=\"max_depth\" success=\"1\"></response>\0", 222) = 222 <0.000178>
10:26:28.823516 recvfrom(4, "feature_set -i 3 -n max_children -v 100\0", 128, 0, NULL, NULL) = 40 <0.000989>
10:26:28.824714 write(4, "220\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<response xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" command=\"feature_set\" transaction_id=\"3\" feature=\"max_children\" success=\"1\"></response>\0", 225) = 225 <0.000106>
10:26:28.824979 recvfrom(4, "feature_set -i 4 -n extended_properties -v 1\0", 128, 0, NULL, NULL) = 45 <0.001083>
10:26:28.826304 write(4, "227\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<response xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" command=\"feature_set\" transaction_id=\"4\" feature=\"extended_properties\" success=\"1\"></response>\0", 232) = 232 <0.000085>
10:26:28.826553 recvfrom(4, "feature_set -i 5 -n notify_ok -v 1\0", 128, 0, NULL, NULL) = 35 <0.000947>
10:26:28.828013 write(4, "217\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<response xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" command=\"feature_set\" transaction_id=\"5\" feature=\"notify_ok\" success=\"1\"></response>\0", 222) = 222 <0.000083>
10:26:28.828268 recvfrom(4, "feature_set -i 6 -n resolved_breakpoints -v 1\0", 128, 0, NULL, NULL) = 46 <0.002878>
10:26:28.831476 write(4, "228\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<response xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" command=\"feature_set\" transaction_id=\"6\" feature=\"resolved_breakpoints\" success=\"1\"></response>\0", 233) = 233 <0.000163>

# 输出检测?
10:26:28.831891 recvfrom(4, "stdout -i 7 -c 1\0", 128, 0, NULL, NULL) = 17 <0.001965>
10:26:28.834330 write(4, "192\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<response xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" command=\"stdout\" transaction_id=\"7\" success=\"1\"></response>\0", 197) = 197 <0.000165>

# 双方核对状态
10:26:28.834733 recvfrom(4, "status -i 8\0", 128, 0, NULL, NULL) = 12 <0.001122>
10:26:28.836063 write(4, "210\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<response xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" command=\"status\" transaction_id=\"8\" status=\"starting\" reason=\"ok\"></response>\0", 215) = 215 <0.000154>
10:26:28.836632 recvfrom(4, "step_into -i 9\0", 128, 0, NULL, NULL) = 15 <0.001137>
10:26:28.838063 write(4, "320\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<response xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" command=\"step_into\" transaction_id=\"9\" status=\"break\" reason=\"ok\"><xdebug:message filename=\"file:///home/speauty/PhpstormProjects/XDebug/index.php\" lineno=\"2\"></xdebug:message></response>\0", 325) = 325 <0.000153>
10:26:28.838377 recvfrom(4, "eval -i 10 -- aXNzZXQoJF9TRVJWRVJbJ1BIUF9JREVfQ09ORklHJ10p\0", 128, 0, NULL, NULL) = 59 <0.001622>
# isset($_SERVER['PHP_IDE_CONFIG'])
10:26:28.840307 write(4, "225\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<response xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" command=\"eval\" transaction_id=\"10\"><property type=\"bool\"><![CDATA[0]]></property></response>\0", 230) = 230 <0.000149>
10:26:28.840594 recvfrom(4, "eval -i 11 -- aXNzZXQoJF9TRVJWRVJbJ1NFUlZFUl9OQU1FJ10p\0", 128, 0, NULL, NULL) = 55 <0.001293>
# isset($_SERVER['SERVER_NAME'])
10:26:28.842200 write(4, "225\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<response xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" command=\"eval\" transaction_id=\"11\"><property type=\"bool\"><![CDATA[1]]></property></response>\0", 230) = 230 <0.000179>
10:26:28.842590 recvfrom(4, "eval -i 12 -- KHN0cmluZykoJF9TRVJWRVJbJ1NFUlZFUl9OQU1FJ10p\0", 128, 0, NULL, NULL) = 59 <0.001478>
# (string)($_SERVER['SERVER_NAME'])
10:26:28.844345 write(4, "278\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<response xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" command=\"eval\" transaction_id=\"12\"><property type=\"string\" size=\"16\" encoding=\"base64\"><![CDATA[d3d3LnhkZWJ1Zy5sb2NhbA==]]></property></response>\0", 283) = 283 <0.000232>
# www.xdebug.local 域名
10:26:28.844695 recvfrom(4, "eval -i 13 -- KHN0cmluZykoJF9TRVJWRVJbJ1NFUlZFUl9QT1JUJ10p\0", 128, 0, NULL, NULL) = 59 <0.001722>
10:26:28.846724 write(4, "257\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<response xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" command=\"eval\" transaction_id=\"13\"><property type=\"string\" size=\"2\" encoding=\"base64\"><![CDATA[ODU=]]></property></response>\0", 262) = 262 <0.000122>
# 85 端口
10:26:28.847028 recvfrom(4, "eval -i 14 -- KHN0cmluZykoJF9TRVJWRVJbJ1JFUVVFU1RfVVJJJ10p\0", 128, 0, NULL, NULL) = 59 <0.000949>
10:26:28.848599 write(4, "302\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<response xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" command=\"eval\" transaction_id=\"14\"><property type=\"string\" size=\"36\" encoding=\"base64\"><![CDATA[L2luZGV4LnBocD9YREVCVUdfU0VTU0lPTl9TVEFSVD0xNTQz]]></property></response>\0", 307) = 307 <0.000136>
# /index.php?XDEBUG_SESSION_START=1543
10:26:28.848951 recvfrom(4, "breakpoint_set -i 15 -t line -f file:///home/speauty/PhpstormProjects/XDebug/index.php -n 2\0stack_get -i 16\0", 128, 0, NULL, NULL) = 108 <0.036324>
# 设置断点
10:26:28.885499 getpid()                = 6992 <0.000009>
10:26:28.885591 write(4, "359\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<notify xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" name=\"breakpoint_resolved\"><breakpoint type=\"line\" resolved=\"resolved\" filename=\"file:///home/speauty/PhpstormProjects/XDebug/index.php\" lineno=\"2\" state=\"enabled\" hit_count=\"0\" hit_value=\"0\" id=\"69920014\"></breakpoint></notify>\0", 364) = 364 <0.000065>
10:26:28.885786 write(4, "223\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<response xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" command=\"breakpoint_set\" transaction_id=\"15\" id=\"69920014\" resolved=\"resolved\"></response>\0", 228) = 228 <0.000053>
10:26:28.885887 write(4, "313\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<response xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" command=\"stack_get\" transaction_id=\"16\"><stack where=\"{main}\" level=\"0\" type=\"file\" filename=\"file:///home/speauty/PhpstormProjects/XDebug/index.php\" lineno=\"2\"></stack></response>\0", 318) = 318 <0.000064>
10:26:28.886041 recvfrom(4, "stack_get -i 17\0", 128, 0, NULL, NULL) = 16 <0.001209>
10:26:28.887338 write(4, "313\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<response xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" command=\"stack_get\" transaction_id=\"17\"><stack where=\"{main}\" level=\"0\" type=\"file\" filename=\"file:///home/speauty/PhpstormProjects/XDebug/index.php\" lineno=\"2\"></stack></response>\0", 318) = 318 <0.000064>
10:26:28.887429 recvfrom(4, "context_names -i 18\0", 128, 0, NULL, NULL) = 20 <0.152711>
10:26:29.040304 write(4, "330\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<response xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" command=\"context_names\" transaction_id=\"18\"><context name=\"Locals\" id=\"0\"></context><context name=\"Superglobals\" id=\"1\"></context><context name=\"User defined constants\" id=\"2\"></context></response>\0", 335) = 335 <0.000928>
10:26:29.041387 recvfrom(4, "context_get -i 19 -d 0 -c 0\0", 128, 0, NULL, NULL) = 28 <0.000169>
10:26:29.041753 write(4, "198\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<response xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" command=\"context_get\" transaction_id=\"19\" context=\"0\"></response>\0", 203) = 203 <0.000141>
10:26:29.042071 recvfrom(4, "context_get -i 20 -d 0 -c 1\0", 128, 0, NULL, NULL) = 28 <0.000995>
10:26:29.043387 write(4, "8546\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<response xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" command=\"context_get\" transaction_id=\"20\" context=\"1\"><property name=\"$_COOKIE\" fullname=\"$_COOKIE\" type=\"array\" children=\"1\" numchildren=\"1\" page=\"0\" pagesize=\"100\"><property name=\"XDEBUG_SESSION\" fullname=\"$_COOKIE[&quot;XDEBUG_SESSION&quot;]\" type=\"string\" size=\"4\" encoding=\"base64\"><![CDATA[MTU0Mw==]]></property></property><property name=\"$_ENV\" fullname=\"$_ENV\" type=\"array\" children=\"0\" numchildren=\"0\" page=\"0\" pagesize=\"100\"></property><property name=\"$_FILES\" fullname=\"$_FILES\" type=\"array\" children=\"0\" numchildren=\"0\" page=\"0\" pagesize=\"100\"></property><property name=\"$_GET\" fullname=\"$_GET\" type=\"array\" children=\"1\" numchildren=\"1\" page=\"0\" pagesize=\"100\"><property name=\"XDEBUG_SESSION_START\" fullname=\"$_GET[&quot;XDEBUG_SESSION_START&quot;]\" type=\"string\" size=\"4\" encoding=\"base64\"><![CDATA[MTU0Mw==]]></property></property><property name=\"$_POST\" fullname=\"$_POST\""..., 8552) = 8552 <0.000112>
# 获取超全局变量[Superglobals]
# 1543

10:26:29.043616 recvfrom(4, "context_get -i 21 -d 0 -c 2\0", 128, 0, NULL, NULL) = 28 <0.009563>
10:26:29.053321 write(4, "198\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<response xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" command=\"context_get\" transaction_id=\"21\" context=\"2\"></response>\0", 203) = 203 <0.000132>
10:26:29.053586 recvfrom(4,

# 下一个
10:26:29.043616 recvfrom(4, "context_get -i 21 -d 0 -c 2\0", 128, 0, NULL, NULL) = 28 <0.009563>
10:26:29.053321 write(4, "198\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<response xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" command=\"context_get\" transaction_id=\"21\" context=\"2\"></response>\0", 203) = 203 <0.000132>
10:26:29.053586 recvfrom(4, "run -i 22\0", 128, 0, NULL, NULL) = 10 <546.710713>
10:35:35.764602 chdir("/")              = 0 <0.000046>
10:35:35.764835 times({tms_utime=3, tms_stime=3, tms_cutime=0, tms_cstime=0}) = 1718671729 <0.000075>
10:35:35.765148 write(2, "\0", 1)       = 1 <0.000044>
10:35:35.765519 write(4, "216\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<stream xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" type=\"stdout\" encoding=\"base64\"><![CDATA[WC1Qb3dlcmVkLUJ5OiBQSFAvNy4zLjI1]]></stream>\0", 221) = 221 <0.000175>
# X-Powered-By: PHP/7.3.25

10:35:35.765973 write(4, "188\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<stream xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" type=\"stdout\" encoding=\"base64\"><![CDATA[DQo=]]></stream>\0", 193) = 193 <0.000399>
# ' '
10:35:35.766655 write(4, "332\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<stream xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" type=\"stdout\" encoding=\"base64\"><![CDATA[U2V0LUNvb2tpZTogWERFQlVHX1NFU1NJT049MTU0MzsgZXhwaXJlcz1XZWQsIDE5LU1heS0yMDIxIDAzOjI2OjI4IEdNVDsgTWF4LUFnZT0zNjAwOyBwYXRoPS87IFNhbWVTaXRlPVN0cmljdA==]]></stream>\0", 337) = 337 <0.000342>
# Set-Cookie: XDEBUG_SESSION=1543; expires=Wed, 19-May-2021 03:26:28 GMT; Max-Age=3600; path=/; SameSite=Strict

10:35:35.767521 write(4, "188\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<stream xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" type=\"stdout\" encoding=\"base64\"><![CDATA[DQo=]]></stream>\0", 193) = 193 <0.000118>
# ' '
10:35:35.768016 write(4, "236\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<stream xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" type=\"stdout\" encoding=\"base64\"><![CDATA[Q29udGVudC10eXBlOiB0ZXh0L2h0bWw7IGNoYXJzZXQ9VVRGLTg=]]></stream>\0", 241) = 241 <0.000105>
# Content-type: text/html; charset=UTF-8

10:35:35.768354 write(4, "188\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<stream xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" type=\"stdout\" encoding=\"base64\"><![CDATA[DQo=]]></stream>\0", 193) = 193 <0.000077>
# ' '
10:35:35.768600 write(4, "188\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<stream xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" type=\"stdout\" encoding=\"base64\"><![CDATA[DQo=]]></stream>\0", 193) = 193 <0.000115>
# ' '
10:35:35.768931 write(4, "188\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<stream xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" type=\"stdout\" encoding=\"base64\"><![CDATA[eDIz]]></stream>\0", 193) = 193 <0.000229>
# 标准输出
# x23

10:35:35.769437 write(4, "208\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<response xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" command=\"run\" transaction_id=\"22\" status=\"stopping\" reason=\"ok\"></response>\0", 213) = 213 <0.000102>
10:35:35.769678 recvfrom(4, "detach -i 23\0", 128, 0, NULL, NULL) = 13 <0.006505>
# 离开
10:35:35.776446 write(4, "211\0<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<response xmlns=\"urn:debugger_protocol_v1\" xmlns:xdebug=\"https://xdebug.org/dbgp/xdebug\" command=\"detach\" transaction_id=\"23\" status=\"stopping\" reason=\"ok\"></response>\0", 216) = 216 <0.000185>
10:35:35.776900 close(4)                = 0 <0.000108>
10:35:35.777224 close(4)                = -1 EBADF (错误的文件描述符) <0.000114>
# 连续关闭, 导致对应fd不存在

最后总结

PHP 而言, 所谓 Debug, 就是定位当前行为及其上下文, 采用 cs 模型, 不过指令由 s 端发出, 是个被动操作. 这里借助 strace 指令分析进程函数调用, 如果再进一步切入 PHP 解释器就更好了. 需要注意的是, 做这种调试, 需要将 PHP 的工作进程( work proccess )设置为1, 确保跟踪进程为当前执行进程.

相关标签: PHP php debug