Debug Remote PHP CLI Scripts

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:


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.

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 exported for all the applications that will run in the current session:

php script.php

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.

export PHP_IDE_CONFIG="serverName=devel-host"
XDEBUG_CONFIG='' php script.php

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.

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.