最近打算研究一下nextcloud和roundcubemail这两个经典项目,正好都是PHP的,很多时候解决问题还是看代码或者调试代码来的直接。
开发调试平台的组成是:
本地开发(192.168.14.117):windows7 pro,Vscode(1.56.2),phpstudy(V8),xdebug;
远程开发(192.168.10.51):CentOS7+nginx+php(7.4)+xdebug+mariadb;
PHP项目(192.168.10.51):roundcubemail
一、本地开发环境的建立
首先是搞定本地开发环境,IDE是Vscode(实际上vscode主要是编辑器,还需要使用外部编译器/解释器),为了方便建立PHP调试环境(WAMP),可以选择xampp或者phpstudy。vscode和phpstudy都是支持windows和Linux的,当然这里还是以习惯的windows 7 pro作为开发环境示例。
1. 建立本地测试运行环境LNMP/WNMP
phpstudy下载https://www.xp.cn/,phpstudy继承了PHP开发的常见组件,注意phpstudy已经是跨平台的,可以在Linux、Docker环境下运行。
windows下是一键安装。
phpstudy集成了众多的组件,包括数据库工具等,也支持多个php版本。
如果在本地做PHP开发和调试 ,就需要启动php-xdebug组件,php-study现在已经内置了相应的组件,配置如下,这里将端口监听配置为9001端口。
同时,phpstudy提供了集中进行配置管理的地方,对系统不熟悉的开发人员而言非常实用。 如下图是php.ini中关于xdebug的配置(remote_enable=on;Nginx会占用9000端口,这里将xdebug端口设置为9001)。
如果phpstudy安装目录是D:\phpstudy_pro,那么WEB根目录默认在D:\phpstudy_pro\WWW。安装完成后,可以用浏览器访问本地:http://localhost,在根目录下建一个D:\phpstudy_pro\WWW\phpinfo.php文件,如下
<?php
phpinfo();
?>
访问http://localhost/phpinfo.php就会显示PHP的安装信息,包括xdebug参数。运行环境OK!
【注】如果xdebug没有显示,可尝试在php.ini中的zend_extension中使用绝对路径试一下。
【注】建议把PHP.exe所在文件夹路径添加进环境变量-系统变量-Path中。这样,在cmd中任何路径下输入php -v,检查是否配置成功。
2. vscode编程环境
vscode当然也支持跨平台。windows一键安装。
开发和调试PHP代码之前,首先是几个插件的安装。
(一)中文支持
安装chinese(simplified)语言包后,快捷键【Ctrl+Shift+p】弹出搜索框,输入“configure display language”,修改locale.json文件下的属性“locale”为“zh-CN”;
(二)PHP调试插件phpdebug
(三)内置的PHP服务器phpserver
点击phpserver的扩展设置,主要是PHP环境、phpserver端口号等,默认服务端口号:3000。
phpserver正确配置后,在项目中php文件编辑界面中,邮件菜单中可以看到phpserver的功能菜单,第一项是启动本项目,自动打开本地浏览器,访问 http://localhost:3000/{project ...}
(四)Vscode绑定PHP解释器
vscode菜单栏:文件->首选项->配置,在右边:用户->扩展->PHP,php.validate.executablePath”的下面点击在settings.json中编辑.,这个界面也可以设置phpserver插件的参数。和本文安装的phpstudy环境对应settings.json文件如下:
{
"php.validate.executablePath": "D:\\phpstudy_pro\\Extensions\\php\\php7.3.4nts\\php.exe",
"phpserver.phpConfigPath": "D:\\phpstudy_pro\\Extensions\\php\\php7.3.4nts\\php.ini",
"phpserver.phpPath": "D:\\phpstudy_pro\\Extensions\\php\\php7.3.4nts\\php.exe",
"phpserver.relativePath": ""
}
完成这几步后,就可以打开一个php项目文件夹,设置断点,默认生成的调试配置名称“Listen for Xdebug”,F5开始调试运行了。
这时,VScode本地PHP开发环境OK!
二、远程调试环境的建立
很多时候,项目不仅仅是在本机开发环境进行开发,还需要在网络中真实服务器环境中进行开发,甚至有些问题需要直接在实际使用的生产服务器进行调试,这就需要建立远程调试开发环境。
1. PHP远程调试的基本原理
远程调试主要是通过Xdebug进行,在远程(被调试的服务器)运行的Xdebug和IDE(本地开发客户端)上的Xdebug通信,这时开发终端的xdebug是server状态。
PHP调试指南(https://zhuanlan.zhihu.com/p/332864496)的过程描述:
- IDE(vscode等) 打开本地的 9000 端口并进行监听(Xdebug 2.X 默认为 9000,Xdebug 3.X 默认为 9003)
- IDE 做好路径映射(path mapping),即本地在IDE中打开的项目目录与远程服务器上的项目目录做一一映射
- 本地向服务器发送请求时带上 Cookie: XDEBUG_SESSION=IDEKEY
- 服务器接受到请求时,经历了 Nginx -> php-fpm 后到达 Xdebug,Xdebug 检测到 XDEBUG_SESSION 的 cookie,认为这条请求是带着 调试目的 来的,同时挂起 PHP解释器 进一步处理请求
- 然后 Xdebug 从 php.ini 中获取目标地址或从 $_SERVER 里获取到请求的来源地址(比如 223.104.148.182)作为目标地址,然后就向目标地址的 9000 端口发起建立 调试连接
- 本地 IDE 发现监听的 9000 端口有 调试连接建立,判断 XDEBUG_SESSION 如为预设的 IDE key,同时发现本地打了断点或者本地设置了 "stopOnEntry": true (VSCode) ,则告诉服务器的 Xdebug,“收到,调试准备就绪”,然后双方协商一下进入调试状态。
2. 路径映射
远程调试实际上对于开发终端的IDE来说,看到的代码目录结构要和远程服务器上的项目目录完全一致。
以前面实施的roundcubemail为例,其部署的位置是服务端192.168.10.51的“/opt/www/roundcubemail/”下面,因此首先要将其映射到开发终端(192.168.14.117)来,可以使用ftp、scp、http、webdav、smb等协议,可以在网上找到相关的具体配置方法,本博客中也有一些文章分别介绍了相关的操作。
不过,在局域网中,最基本是用SAMBA(smb)方式,在服务器上将“/opt/www/”或者“/opt/www/roundcubemail/”设置为共享目录,然后在开发终端上映射网络驱动器将其映射为一个盘符,如下。
服务端samba的配置文件大致如下(这里,提前建了一个samba用户,密码123456),后面是/opt/www下的目录。
[root@mx ~]# cat /etc/samba/smb.conf
[global]
workgroup = workgroup
security = user
passdb backend = tdbsam
[www]
comment = opt is www's root
path = /opt/www
browseable = yes
writable = yes
admin users = samba
valid users = samba
create mask =0777
directory mask =0777
......
[root@mx ~]# ll /opt/www
总用量 24
drwxrwxrwx 18 root root 4096 5月 4 00:07 cacti
-rw-r--r-- 1 root root 78 5月 28 10:54 index.html
lrwxrwxrwx. 1 root root 22 5月 25 16:25 iredadmin -> /opt/www/iRedAdmin-1.3
dr-xr-xr-x. 12 nginx nginx 4096 6月 2 15:37 iRedAdmin-1.3
lrwxrwxrwx 1 root root 30 5月 28 11:14 mail -> /opt/www/roundcubemail-1.4.11/
drwxr-xr-x 14 nginx nginx 4096 6月 2 09:14 nextcloud
-rw-r--r-- 1 root root 21 5月 28 10:54 php.php
lrwxrwxrwx. 1 nginx nginx 29 5月 25 16:25 roundcubemail -> /opt/www/roundcubemail-1.4.11
drwxr-xr-x. 14 nginx nginx 4096 6月 8 14:54 roundcubemail-1.4.11
然后,在windows开发终端映射该共享为盘符【Y】:
这时候要测试一下,在共享目录【Y】盘是否有写入文件和删除文件等权限。如果没有相应权限,需要在服务端/opt/www目录进行设置权限(开发阶段简单粗暴的方法是: chmod 777 /opt/www)。
OK!这样路径就完全映射好了。
3. 服务器上的启用xdebug
首先,在服务器192.168.10.51上,安装和启动xdebug,php74环境参考前文。
yum install -y php74-php-pecl-xdebug
【注】php74默认安装的xdebug是2.9.8
然后对php.ini参数进行设置,xdebug配置项单另在/etc/opt/remi/php74/php.d/15-xdebug.ini文件中,主要修改是:
xdebug.remote_enable = 1
xdebug.remote_autostart = 1
xdebug.remote_host = 192.168.14.117
xdebug.remote_port = 9001
xdebug.remote_connect_back = 0
xdebug.remote_log = /var/log/xdebug.log
其中remote_enable是启用远程调试;远程调试主机地址是vscode开发终端192.168.14.117,端口是9001;
同时,指定单独的日志文件,日志对于排查问题非常关键。检查日志文件身份是否有操作权限,如:chmod 666 /var/log/xdebug.log。
4. vscode远程调试配置
在vscode中打开共享目录【Y】盘的roundcubemail目录(项目),然后进入项目调试窗口,打开项目的launch.json文件,可以看到里面默认有刚才本地调试的调试配置名称“Listen for Xdebug”,为远程调试增加一个调试配置“Remote for Xdebug”,如下:
{
"version": "0.2.0",
"configurations": [
{
"name": "Listen for Xdebug",
"type": "php",
"request": "launch",
"port": 9001
},
{
"name": "Remote for XDebug",
"type": "php",
"request": "launch",
"pathMappings": {
// "远程机上代码地址(本文为虚拟机共享文件地址)": "本机代码地址"
"/opt/www/roundcubemail-1.4.11": "${workspaceRoot}"
},
"port": 9001 // 和远端服务器的xdebug设置一致
},
......
}
现在,在调试界面中,选择“Remote for XDebug”就可以进行远程调试,设好断点,在服务器上访问到相应的php程序,就会自动在断点处停下来。
【注】如果不能进入断点,先判断断点位置是否正确,再查看远程服务器上xdebug日志 /var/log/xdebug.log,根据日志信息来修正xdebug参数等。
5. 防止调试超时
Vscode在断点时间过长的情况下页面容易出现 504 Gateway Timeout 的超时错误,需要执行环境中以下三个文件做相应配置,如设置1200秒超时:
- PHP配置:在 /etc/php.ini (本文配置是/etc/opt/remi/php74/php.ini)中修改最长执行时间 max_execution_time = 1200(默认单位为秒)
- PHP-FPM配置:在 /etc/php-fpm.d/www.conf(本文配置是/etc/opt/remi/php74/php-fpm.d/www.conf) 中修改请求终止超时时间 request_terminate_timeout = 1200(默认单位为秒)
- Nginx配置:在 /etc/nginx/nginx.conf (本文配置是/etc/nginx/conf-enabled/php_fpm.conf)中 http 内增加请求终止超时时间 fastcgi_read_timeout 1200;(默认单位为秒)
重启 php-fpm 和 nginx 服务生效。
6. 直接调试生产服务器(ssh隧道)
这里主要是指直接在互联网上部署,比如公有云平台等上的PHP应用。另外一种用途是日常开发中,比如需要把内网开发机器上的开发版本给外网用户演示用。
在参考资料PHP调试指南(xdebug)中详细分了三种情况:
- 本地开发和远程服务器可处于同一个直接可达网络(包括VPND),这就和上面的操作无区别;
- 本地开发网中路由器获取到了 公网IP,端口映射将本地的 9001端口映射到路由器的 公网IP的9001 端口,然后操作也和上面无区别;
- 没有公网IP,可以采用SSH 反向隧道将本地的 9001 端口映射到服务器的 9001 端口。这样服务器上的 Xdebug 访问9001 就等于访问到了 IDE本地 的 9001 端口
(1)在开发机的powershell中执行 下面的映射命令:
# SSH 隧道 反向将本地的 9001 端口映射到服务器(www.myserver.com)的 9090 端口上
# 后台执行(-f),不实际连接而是做port forwarding(-N),做反向ssh(-R)
ssh -g -N -R 9090:127.0.0.1:9001 remotedev@www.myserver.com
# 也有例子 [::]:9090 是将9090端口绑定在所有网口
ssh -p 22 -qngfNTR "[::]:9090:localhost:9001" remotedev@www.myserver.com
(2)服务器上修改ssh服务配置文件:/etc/ssh/sshd_config,修改配置项:
GatewayPorts =yes
防火墙设置:
firewall-cmd --zone=public --add-port=9090/tcp --permanent
firewall-cmd --reload
这实际上就是内网穿透技术,搭建好的话,可以实现在家中无缝使用开发服务器、生成服务器进行开发、部署升级和演示等。
参考资料:
- PHP调试指南,https://blog.chaosjohn.com/Debug-php.html,介绍了xdebug helper的使用,以及在以接口为主要开发内容场景下使用curl和postman的方法
- PHP调试指南(xdebug),https://zhuanlan.zhihu.com/p/332864496,介绍了ssh反向隧道的建立,还有dbgp多人调试的介绍,特别是例子同时有xdebug2和xdebug3的配置
- https://my.oschina.net/surjur/blog/3062984,有xdebug参数详细解释,xdebug版本2和版本3的配置有不小的区别,本文都是xdebug2版本。
- Xdebug Helper for Firefox,https://addons.mozilla.org/en-GB/firefox/addon/xdebug-helper-for-firefox/
- https://blog.csdn.net/bugonline/article/details/42233473 通过XShell 的SSH隧道功能, 让外网访问内网网站
- https://www.cnblogs.com/kevin7234/p/10630414.html 利用ssh隧道5分钟搞定内网穿透
- https://blog.csdn.net/uisoul/article/details/97416567 外部网络SSH访问公司内网服务器终极解决方案(实现SFTP直连内网)
- https://blog.csdn.net/qq_33235166/article/details/84452435 利用xshell的ssh隧道反向穿透,微信公众号的事件会转发到本地进行调试