I had to debug a command line PHP script that runs on a remote server and I could not figure out how to do it. I am using PhpStorm and XDebug.
PhpStorm comes with a rich set of configurations to run a PHP script, including a couple of presets for debug. I used them to debug web pages and command line scripts running on the local computer but nothing worked for scripts running on remote servers.
By reading the documentation of XDebug and PhpStorm I learned that some small tasks must be accomplished in order to make PhpStorm and XDebug co-operate for debugging.
Installing and configuring XDebug
Installing XDebug depends on the OS that runs on the remote server and everything is explained in the XDebug documentation.
A single line of configuration is required. In php.ini
add:
1 | xdebug.remote_enable=1 |
Starting the debugger client
Due to the way the PHP scripts are invoked by the web server, the communication between the PHP debugger extension and the debugger client (the IDE) is initiated by the PHP extension. The IDE must be told to start listening for connections first. PhpStorm has a entry in the Run menu named Start Listen for PHP Debug Connections to accomplish this task.
Starting the debugger extension
Because debugging is not the normal way to run a PHP script, the debugging does not start by only installing and configuring the XDebug extension. It requires the presence of a special variable in the request or in the environment.
For CLI scripts this is the environment variable XDEBUG_CONFIG
. While its mere presence is enough
to start the debugging, its content is also important: it can be used to override the values declared in php.ini
.
More details in the XDebug documentation.
1 | XDEBUG_CONFIG='' php script.php |
By prepending the command line with the initialization of the environment variable, the variable is set only
for that specific execution of the PHP interpreter. To make the variable available on the subsequent commands
it should be set in the shell and export
ed for all the applications that will run in the current session:
1 | export XDEBUG_CONFIG='' |
This is not always the best option but it can help if you are expecting a heavy debug session.
Configuring path mapping
Because on the remote host the script is usually located on a different path than on the local machine,
PhpStorm needs a way to know how to map the remote path to the local path. When the debug session starts,
PhpStorm asks the debugger about the value of the environment variable PHP_IDE_CONFIG
(if it is set.)
Its value should look like serverName=name
where ‘name’ is the name of the server configured in
Project Settings->PHP->Servers.
The most convenient way to set this variable to the debugged script is to pass it to the interpreter as an environment variable.
1 | export PHP_IDE_CONFIG="serverName=devel-host" |
Check this post on PhpStorms’s blog for details.
What else is missing?
I followed all the steps above by the book, double checked them, but the remote debugger continued to ignore all my efforts. I searched on the Internet but the directions I could find did not help very much. So, I went back to the documentation.
XDebug provides an exhaustive description of how to set up remote PHP debugging. It explains there how the debug extension communicates with the client program (PhpStorm, in my case) and this was the starting point on the path to the solution of the problem.
Back to the XDebug configuration, xdebug.remote_connect=1
tells it to attempt to connect
to the host defined by xdebug.remote_host
on port defined by xdebug.remote_port
. The default values for
them are localhost
and 9000
.
Keep in mind that localhost
refers to the host where the XDebug runs and that is the remote host and not
the machine where the PhpStorm runs. This is why XDebug cannot communicate with PhpStorm.
Setting xdebug.remote_host
to the IP address of the local machine should do the trick, except that I cannot
make it work. The remote server where the PHP scripts run is somewhere in the Internet. The workstation where
PhpStorm runs is connected to a LAN that is behind a firewall. It uses an intranet IP address (192.168.*.*
)
and this (and the firewall) prevents the XDebug extension to call back to the IDE in order to start debugging.
Eventually, the solution
The solution is simple: create a SSH tunnel from port 9000
on the remote server to port 9000
of the local
machine.
In order to start the PHP script on the remote server, I already log into the remote machine using ssh
.
All I had to do was to log out then log in again appending -R 9000:localhost:9000
to the ssh
command line.
1 | ssh user@remote-host -R 9000:localhost:9000 |
Then I set up the environment variables as above, started the PHP script and the magic happened.