How to debug php on remote server?

I’ve talked about debugging php using netbeans. Debugging php locally is relatively easy. You only need to install apache server such as xampp/wampp on your PC, and put your website in the root directory, then enable xdebug in php.ini. When creating a new project in Netbeans, you choose “PHP Application with Existing Sources”, then select the root directory of your website as the “Sources Folder”.

However, some day, you may need to debug php online. This is because typically, you deploy your website on a remote Linux server. You may find it impossible to replicate the production environment on your local PC. You can still install IDE such as Netbeans on Linux server to debug the problem of your website on the server just as you debug the website locally on your pc. But that requires you install a desktop environment on Linux, which is impractical in some cases due to limitations such as low memory, etc. You’d better install the IDE on your Windows/Mac PC and debug the php website on remote Linux server.

Theoretically, it is impossible to debug php web page remotely because debugging is to show the php source code in IDE then step over/step into/set breakpoints in the source code. However, you cannot get the php source by just visiting the website. The content displayed on your browser is the html that is generated by apache from php, not the php code itself. But netbeans can fetch the php source code using ftp/sftp between your local PC and the remote server and display them in its IDE window, so you can trace the execution of the source code as if they reside on your local machine. You just need to specify the “PHP Application from Remote Server” option when creating the netbeans project.

Click Next, you still need to set the “Sources Folder“. But that’s only the local copy of the php code. Then, you need to set the “Project URL“(the php website you want to debug), the “Remote Connection“(the ftp information that is used to get the php source code from the remote server), and the “Upload Directory“(if the ftp home directory is not the same as the root directory of the website).

After clicking Next, Netbeans will start to fetch the php source code from the server. If your website has many files, the process will take long time because ftp is usually slow. After all files are downloaded to local machine, you can start to debug the website as you do for local projects.

Before you start to debug the remote website, you need to do some configuration on your server. You need to install xdebug on your server. Use the following command to find a xdebug package to install in CentOS:

yum list|grep xdebug

You may get this one: php-pecl-xdebug3.x86_64

This is xdebug version 3. Install it:

yum install php-pecl-xdebug3.x86_64

xdebug config location has been changed in xdebug 3.  Unlike older version of xdebug which puts its ini settings in /etc/php.ini, xdebug3  config file location is /etc/php.d/15-xdebug.ini(installed by php-pecl-xdebug3.x86_64). Php7 will load all .ini files in /etc/php.d/ after load the main .ini file /etc/php.ini. You can use the following command to show exactly what .ini files are loaded by php:

php --ini

After restarting apache, xdebug is enabled by default. But you may not want to enable xdebug in production environment. To disable xdebug, you need to edit  /etc/php.d/15-xdebug.ini. php to comment the following line:

;zend_extension=xdebug.so

Many xdebug options for xdebug2 have been renamed or removed in xdebug3. You may find the following xdebug 2 ini example:

;xdebug.remote_log="/tmp/xdebug.log"
;xdebug.profiler_enable = 1
;xdebug.remote_enable=on
;xdebug.remote_port=9000
;xdebug.remote_autostart=0
;xdebug.remote_connect_back=on
;xdebug.idekey=editor-xdebug

The remote_xxx options such as remote_port are unrecognized in xdebug 3. In xdebug3, you just need to write a few lines to set it up.

zend_extension = /usr/lib64/php/modules/xdebug.so
xdebug.mode=debug
xdebug.client_host=localhost
xdebug.client_port=9003
xdebug.idekey="netbeans-xdebug"

Xdebug setup is not hard, but after you set up xdebug, you may find you cannot debug in Netbeans yet. When you click “Debug Project” or press Ctrl+F5 in Netbeans, the execution does not stop at somewhere in the source code. To resolve this problem, you need to understand how xdebug works.

When debugging a project, Netbeans will start a local server listening on port 9003. When you visit the debugged website with a query parameter XDEBUG_SESSION_START=netbeans-xdebug, the xdebug module in apache will be aware that it is in debug mode now, and the session name is netbeans-xdebug(specified by the xdebug.idekey option), then it will pause the interpretation of php code and connect to the peer host(your PC, specified by the xdebug.client_host option) on port 9003(specified by the xdebug.client_port). You PC accepts the connection and Netbeans will communicate with the remote xdebug to instruct it where to stop(set up breakpoints) and get the state information such as values of php variables to display in IDE. The reason Netbeans chooses to use a server instead of querying remote server to get the state information and set breakpoints is that Netbeans does not know the execution time of php code so it cannot decide a reasonable query interval. Xdebug knows exactly how the php is executed, thus can report to the server started by netbeans at appropriate time.

We see here two connection directions: the browser visits remote server in forward direction and the remote httpd server(xdebug enabled) connects to netbeans in backward direction. The backward connection may cause problem for some developers because some ISPs may block the backward connection from external internet to your home broadband(you cannot change the connection mode of your home broadband from NAT mode to Bridge mode) or do not allow their customers to add NAT mapping entries in their router configurations. Simply speaking, some guys may find the remote server cannot set up the backward connection to the Netbeans server on your local PC. Without getting messages from remote xdebug, netbeans cannot perform the debug and stays in the status of waiting for connection from xdebug.

Don’t give up even you cannot connect from internet to your home PC. We can resort to ssh reverse tunnel. With an ssh backward tunnel, the remote server can connect to netbeans. And if you can ssh to the remote  server, you can create an ssh reverse tunnel. We use putty to create a reverse tunnel. You may already know how to create a putty forward tunnel, which is often used in vnc. The following is a putty tunnel setup example:

Here, you fill source port 1234, Destination myprogrammingnotes.com:22, choose Local, then click Add, you’ll find the string “L1234 myprogrammingnotes.com:22” appears in the “Forwarded ports” box. L1234 means local port 1234. After setting up the forward tunnel, you can login to the remote server, then you will find putty creates a server listening on port 1234 on your PC waiting for connections. When some client connects to the server, putty will transfer the data the client passes to it to the remote sshd server on myprogrammingnotes.com. Sshd on remote server receives the data and further passes it to some application listening on port 5678 on myprogrammingnotes.com.

The following is a putty reverse tunnel example:

To set up a putty reverse ssh tunnel, fill “Source port” 1234, “Destination” 127.0.0.1:5678, choose “Remote“, then click Add. The string “R1234  127.0.0.1:5678” will appear in the “Forwarded ports” box. Here, R1234 means remote port 1234. To understand what the source and destination are, you should know that a putty ssh tunnel has a direction; data(more previously connection) flows in that direction. The source means the end of the tunnel where data enters, while the destination means the end of the tunnel that data exits. Since the forward tunnel forwards data from local machine to remote server, the source port means the port on your local PC while the destination means the address/port of the remote server. In the case of reverse tunnel, the data flows from the remote server to your local PC, so the source port means the port on remote server and the destination is the local address and port on local machine. Note that putty only creates a server on source end on source port. The port in destination is the port opened by some other application. After setting up the backward tunnel, you can login to the remote server, then sshd on myprogrammingnotes.com will create another server listening on port 1234(remember to add a line “GatewayPorts yes” in /etc/ssh/sshd_config and restart sshd).

To use netbeans to debug php on remote server, you need to set the source port and the destination port to 9003 for the ssh reverse tunnel because you set xdebug.client_port=9003 in xdebug.ini. Xdebug will connect to localhost(i.e.,the remote server, specified by xdebug.client_host=localhost), the server created by sshd listening on port 9003 will pass the connection to your PC and connect to the sever created by netbeans listening on port 9003 on your pc. Then, netbeans and xdebug will communicate with each other to do the remote debugging.

Posted in

Leave a Reply