Welcome to reprint, but please quote the original source at the beginning or end.
preface
At the beginning of the previous PHP debugging guide (Xdebug edition), I said, “Read through this article and no one will know PHP Xdebug better than you.” I didn’t expect to hit the face so fast, this only after three or four days, I found that today I than I wrote before, more understand.
PhpStorm 2020.3 and Xdebug 3
In the previous article, I used PhpStorm 2020.2.4, so when using Web Server Debug Validation with Xdebug 3.0.0 for debugging environment Validation, Error message similar to Xdebug port is invalid is displayed. This error is caused by incompatible version 3.0.0. So I demoted to Xdebug 2.9.8 to finish the article.
PhpStorm 2020.3 was released the day after I wrote the previous article
- right
PHP 8
The support of - right
Xdebug 3
The support of
After reinstalling the PHP 8 + Xdebug 3.0.0 environment with PHPBrew and deploying it with Nginx + php-fPM, The Web Server Debug Validation succeeds.
aboutWeb Server Debug Validation
function
After writing the above article, I reinstalled PHP 7.4.13 + Xdebug 3.0.0 before upgrading PhpStorm 2020.3. There was no problem when I directly started debugging without ignoring the verification error. Therefore, this function only verifies the debugging environment and is used for reference only before debugging, without affecting actual debugging.
aboutRemote debugging
When I wrote the previous section on remote debugging, I referred to a lot of articles on the Internet. It seems to be thoroughly understood, but in fact it is not, for several reasons:
- The author of many articles on the Internet also wrote the same as the author wrote the previous article, to the principle of the half-understanding, leading to a lot of explanation is not perfect or contradictory. In: Study
JetBrains
/VSCode
/Xdebug
To understand how it works.- Configure Xdebug — PhpStorm PhpStorm
- Remote debugging via SSH tunnel – PhpStorm PhpStorm official: Remote debugging through SSH tunnel
- Multiuser debugging via Xdebug proxies — PhpStorm PhpStorm official: Multiple debugging through the Xdebug agent
- PHP Debug Adapter for Visual Studio Code
- Step Debugging Xdeubg Official: Single-step Debugging
- Documentation – All Settings Xdebug official: All configuration items
- Upgrading Xdebug from Xdebug 2 to Xdebug 3
- I wrote the previous article when the construction
Remote debugging environment
imperfect- This machine 和 Remote serverAre all
macOS
- This machine 和 Remote serverAll in
Within the local area network (LAN)
- This machine 和 Remote serverAre all
IDE
In combination withXdebug
Principle of Debugging
IDE (by itself or with plug-ins)
Open local9000
Port and listens (Xdebug 2.X defaults to9000
, Xdebug 3.X The default value is9003
, but can be modified)IDE (by itself or with plug-ins)
Do the path mapping (path mapping
That is, the project directory opened locally in the IDE is mapped to the project directory on the remote server, for example- MacOS local:
/Users/chaos/Work/php/demos/debug/
- Linux server:
/home/chaos/Work/php/demos/debug/
- MacOS local:
- When the local sends a request to the server
Cookie: XDEBUG_SESSION=IDEKEY
- The server experienced an error when receiving the request
Nginx
->php-fpm
After the arrivalXdebug
.Xdebug
detectedXDEBUG_SESSION
的cookie
, this request is considered to be withDebugging purposes
Yes, and hang it at the same timeThe PHP interpreter
Further processing the request - then
Xdebug
从php.ini
Gets the destination address from or$_SERVER
To retrieve the source address of the request (e.g223.104.148.182
) as the destination address, and then to the destination address9000
Port InitiationDebug connection
- The local
IDE (by itself or with plug-ins)
Detected listening9000
Port has aDebug connection
Establish, judgeXDEBUG_SESSION
Whether preset for oneselfIDE key
- If it’s not preset
IDE key
Through the9000
On the portDebug connection
Tell the serverXdebug
“, “Do not belong to my management, I do not deal with”, and then both sides negotiate to disconnect - If it’s default
IDE key
At the same time, a breakpoint is set locally or a breakpoint is set locally"stopOnEntry": true
(VSCode) /Break at first line in PHP scripts
PhpStorm tells the serverXdebug
“, “Roger, ready for debugging”, and then the two sides negotiate to enter the debugging state
- If it’s not preset
In the real worldRemote debugging 的 trap
The smart ones may have spotted a pitfall in the debugging process above: That is, the server needs to request the local to establish a debugging connection, but the problem is that now all the home/enterprise network environment, the so-called local router under the NAT, there is no exposed IP address in the public network, so the local 9000 port for the server, is unreachable, want to access, dream!
Fill in the pittrap
The author re-simulates the real debugging environment, that is, macOS is the local and two Linux servers are selected for the remote server, one is the physical machine built by the author in the company, and the other is the aliyun cloud host purchased by the company.
The ultimate purpose of pit filling is to expose the local 9000 port to the server and make it directly reachable.
This points:
- Local and remote servers reside on the same LAN, for example, joining the same server
VPN
Network, local accessVPN
Assigned to the serverPrivate IP
Access to the server, server ofXdebug
The source address that is parsed also passesVPN
Assigned locallyPrivate IP
Directly accessible. - The router itself comes from
ISP (Broadband operator)
throughPPPoE dial
Access to thePublic IP
And then pass through the routerPort mapping
或The DMZ mode
, will be local9000
Port, mapped to the router9000
Port so that the server can also pass throughPublic IP: 9000
Access to the local9000
Port. (This method is most recommended, but feasible in China is not high, because domesticThe IP address pool
It’s going to dry up, so it’s hard to get it from the carrierPublic IP
) - Other environments can only be relied uponGraft: with the help of
SSH Reverse Tunnel
To create a link between the local and the serverThe TCP channel
, will be local9000
Port mapped to the server9000
Port. In that case, on the serverXdebug
accesslocalhost:9000
That’s accessIDE of the local
的9000
Port. (Borrow an illustration from the official JetBrains documentation.)
Here, the author summed up the first two environments as the return network is directly accessible, otherwise it is the return network is not direct.
PhpStorm
Special configuration of
Before listing the specific configuration of remote debugging parameters, I also need to separate out the special configuration of PhpStorm.
PhpStorm debug target Server to Server is configured, the specific Languages in preferences and Frameworks | | PHP Servers. See JetBrains’ official documentation for more details.
On this page, configure HTTP access for debugging engines to interact with local and remote Web servers and set correspondence between files on the server and their local copies in the PhpStorm project.
On this page, configure HTTP access for debugging to interact with local and remote Web servers, and associate files on the remote server with local copy Settings opened in the PhpStorm project.
Special configuration for PhpStorm debugging: add these two lines to the phP-fPM configuration file on the remote server:
clear_env = no
env["PHP_IDE_CONFIG"] = "serverName=UbuntuServer"
Copy the code
Here UbuntuServer is a custom server name that you can change yourself.
Then in PhpStorm preferences of Languages and Frameworks | | PHP Servers to add a Server
name
填UbuntuServer
Host
和Port
The author can fill in any legal value,PhpStorm
Not check, so I filled in0
值Debugger
chooseXdebug
- Check on
Use path mappings
And set it upLocal file directory path
和Server file directory path
For example, the author’s local mapping/Users/chaos/Work/php/demos/debug/
With the server/home/chaos/Work/php/demos/debug/
)
VSCode
The configuration of the
You only need to configure one more path mapping than native debugging, namely the pathMappings key value pair, along with the contents of the launch.json file:
Configurations ": [{"version": "0.2.0", "Configurations ": [{"name": "Listen for XDebug", "type":" PHP ", "request": "launch", "port": 9000, // "stopOnEntry": true, "pathMappings": { "/home/chaos/Work/php/demos/debug/": "${workspaceRoot}/", } }, { "name": "Launch currently open script", "type": "php", "request": "launch", "program": "${file}", "cwd": "${fileDirname}", "port": 9000 } ] }Copy the code
“/ home/here chaos/Work/PHP/demos/debug/” :” ${workspaceRoot} / “is”/home/chaos/Work/PHP/demos/debug/” : “/ Users/chaos/Work/PHP/demos/debug/” simplified form, ${workspaceRoot} is VSCode opened in the root directory of the project.
The server’sphp.ini
Configuration in different situations
Case 1:The return network is directly accessible
- Xdebug 2.X
[xdebug]
xdebug.remote_enable=1
xdebug.remote_connect_back=1
Copy the code
| remote_enable = 1 said open remote debugging
| remote_connect_back = 1 said get request launched address (from $_SERVER [‘ HTTP_X_FORWARDED_FOR] and $_SERVER [‘ REMOTE_ADDR] extract), Reverse access to the 9000 port of the originating address to establish a debugging connection
- Xdebug 3.X
[xdebug]
xdebug.mode=debug
xdebug.discover_client_host=true
xdebug.port=9000
Copy the code
| mode = debug replaced 2 X version remote_enable = 1
| discover_client_host = true to replace the 2 X version of the xdebug. Remote_connect_back = 1
| port = 9000 is a personal preference, in 3. The default is 9003 X. I prefer to be consistent with 2.x, so that the same IDE configuration can be debugged for both 2.x and 3.x versions
Situation 2:The return network is not direct
Map the local 9000 port to the server 9000 port using SSH tunnels
SSH -g-n-r 9000:127.0.0.1:9000 user@serverCopy the code
- Xdebug 2.X (Method A)
[xdebug] xdebug. Remote_enable = 1 xdebug. Remote_host = 127.0.0.1Copy the code
| remote_host = 127.0.0.1 said directly to 127.0.0.1 debug connection to this address the request
- Xdebug 2.X (Method B)
[xdebug]
xdebug.remote_enable=1
xdebug.remote_connect_back=1
xdebug.remote_addr_header="HTTP_X_XDEBUG_REMOTE_ADDR"
Copy the code
| remote_connect_back = 1 said get request address, reverse access address debug connection to port 9000
| xdebug. Remote_addr_header = “HTTP_X_XDEBUG_REMOTE_ADDR” said priority from $_SERVER [‘ HTTP_X_XDEBUG_REMOTE_ADDR] get a address, $_SERVER[‘ HTTP_X_FORWARDED_FOR’]; $_SERVER[‘REMOTE_ADDR’]
| debug request is similar to the $curl server.com – 8000 – b XDEBUG_SESSION = IDEKEY -h “X – Xdebug – Remote – Addr: 127.0.0.1”
| note: HTTP – send request need not add, because for custom header, Nginx automatically add prefix.http_, and all caps, dash to underline, deposited in the $_SERVER global variable
- Xdebug 3.X (Method A)
[xdebug] xdebug. Mode = debug xdebug. Port = 9000 xdebug. Client_host = 127.0.0.1Copy the code
| client_host = 127.0.0.1 said directly tell Xdebug, address is 127.0.0.1, to the address you request debug connections
- Xdebug 3.X (Method B)
[xdebug]
xdebug.mode=debug
xdebug.port=9000
xdebug.discover_client_host=true
xdebug.client_discovery_header="HTTP_X_XDEBUG_REMOTE_ADDR"
Copy the code
| client_discovery_header = “HTTP_X_XDEBUG_REMOTE_ADDR” replaced the 2 X version of the xdebug. Remote_addr_header = “HTTP_X_XDEBUG_REMOTE_ADDR”
Xdebug 2.x (Method B) is slightly different from Xdebug 3.x (Method B) :
Xdebug 2.X (Method B)
If the request originating address is not found according to the configuration rules, it is not degraded127.0.0.1 localhost /
As the originating address of the requestXdebug 3.X (Method B)
If the request originating address is not found according to the configuration rules, it is degraded127.0.0.1 localhost /
As the originating address of the request
Multiplayer debugging – DBGp
Attach the reference documents first
- Multiuser debugging via Xdebug Proxies PhpStorm Official: Perform multiple debugging via DBGp proxies
- DBGp Proxy Tool Xdebug Official
Not only am I going to skip this one, I’m going to make fun of it. Take a look at an illustration from the above article “Multiuser Debugging via Xdebug Proxies”
It seems wonderful, isn’t it, but after downloading dbgpProxy and experimenting with it repeatedly, I found that the tool is really a magic pit.
I ran it on aliyun/dbgpProxy -i 0.0.0.0:9001 -s 127.0.0.1:9000
Post from localPhpStorm
Bring customIDE key
"PS"
Initiate a debug request and resultdbgpProxy
Log printConnecting to 112.3.2.42:9000
And the local broadband where the author lives does not have public IP.112.3.2.42
This IP is multi-layeredNAT
The old IP, of course, can’t get in, only upSSH Tunnel Scheme
.
So what’s the point of dbgpProxy? I found an article on the Internet by Derick Rethans, author of Xdebug (who also designed DBGp protocol) – Debugging with Multiple Users. In this article, he described DBDp usage scenarios:
Running a DBGp proxy also allows you to avoid NAT issues where (as seen from PHP+Xdebug on the server) all connections seem to come from the same IP (because your internal network is NATted). In this case, you can simple run the dbgp proxy on your NAT machine, configure xdebug.remote_host setting to the IP address of your NAT machine, and configure the IDEs to connect to the proxy running at :9001.
To paraphrase:
- Your router has to get a public IP address from an ISP
- Run it on your router
dbgpProxy
- For everyone under the router
IDE
的DBGp Proxy configuration
的Host
Enter the router gateway, that is, the Intranet address of the router
From here, you can find that setting up DBGp debugging environment is very demanding. Combining public IP and router running dbgpProxy, only soft routing can meet the requirements. Because dbgpProxy binary executables are available only in Windows/macOS/Linux x86-64 versions. So most people/companies can go to bed.
conclusion
In order to write these two articles, the author did a lot of experiments, also sorted out a lot of knowledge points, made a lot of drafts (paper drafts in the real sense), and finally attached the most satisfactory one.
I hope you found it interesting, and thanks for reading!