Debugging CLI PHP with Zend Server and PDT on Linux and Mac

I'm working on a small PHP application and a big part of it are some CLI scripts which will be executed in the background. Some of these scripts are quite complex, and I got to a point where I need to use a debugger in order to figure out what's going on.

I started hacking around with my locally-installed Zend Server CE and Zend Studio. I always knew how to manually start CLI debug sessions with Zend Studio (well, I knew, but forgot ;-) ), but then I figured, why not write a small shell script to automate the process, and learn a little about the Zend Debugger protocol on the way?

Here is what I did:

First, create the following shell script. I placed it at /usr/local/zend/bin/php-dbg (alongside the other Zend Server executables, which if you use Mac OS X will be at /Applications/ZendServer/bin):

CODE:
  1. #!/bin/sh
  2.  
  3. # Wrapper script for debugging PHP CLI scripts with Zend Studio
  4. # Tested with Zend Server 4.0.0 Beta and Zend Studio for Eclipse 6.1.1
  5. # Shahar Evron [shahar.e at zend], 2009-02-20
  6.  
  7. # Defaults
  8. DFLT_PORT="10137"
  9. DFLT_HOST="127.0.0.1"
  10. DFLT_PARAMS="debug_fastfile=1&use_tunneling=0"
  11.  
  12. # Load Zend Server environment variables
  13. . /etc/zce.rc
  14.  
  15. # Did the user specify the debug host / port?
  16. if test "x$DEBUG_HOST" != "x"; then
  17.   if test "x$DEBUG_PORT" != "x"; then
  18.     QUERY_STRING="&debug_port=$DEBUG_PORT"
  19.   else
  20.     QUERY_STRING="&debug_port=$DFLT_PORT"
  21.   fi
  22.  
  23.   QUERY_STRING="$QUERY_STRING&debug_host=$DEBUG_HOST&$DFLT_PARAMS"
  24.  
  25. # If no host/port were specified, try to auto-detect
  26. else
  27.   QUERY_STRING=`wget http://localhost:20080/ -O - 2> /dev/null`
  28.   if test $? -ne 0; then
  29.     # Fall back to defaults
  30.     echo "Unable to auto-detect Zend Studio settings, using defaults">&2
  31.     QUERY_STRING="&debug_port=$DFLT_PORT&debug_host=$DFLT_HOST&$DFLT_PARAMS"
  32.   fi
  33. fi
  34.  
  35. DBG_SESS_ID=`date +%s`
  36. QUERY_STRING="start_debug=1&debug_stop=1$QUERY_STRING&debug_session_id=$DBG_SESS_ID"
  37.  
  38. QUERY_STRING=$QUERY_STRING $ZCE_PREFIX/bin/php -c $ZCE_PREFIX/etc/php.ini $@

Going over this code might teach you some surprising things about how Zend Debugger and Zend Studio talk to each other ;) I'm not going to go into the details now, but if you have questions feel free to ask.

Next, make this script executable - just run 'chmod +x <path-to-script>' - and you're good to go.

Here is how to use it:

  • If you have PDT or Zend Studio running locally (on the same machine as the server), just run:

    # /usr/local/zend/bin/php-dbg <script you want to debug>

    That would just work in most cases - if it works you can stop reading now ;-)
  • If you are running the script on a server, but your PDT / Zend Studio is on a different machine (in the same LAN - no NAT or firewall!) you can simply specify the IP address or host name of the machine that runs PDT / Zend Studio as the DEBUG_HOST environment variable. For example:

    # DEBUG_HOST=10.1.2.3 /usr/local/zend/bin/php-dbg <script you want to debug>
  • If you are running the script on a remote machine (as above) and your Zend Studio listens on a port other than 10137, you can also pass the DEBUG_PORT environment variable to override the default port.
  • Also, don't forget to make sure that the machine that runs your Zend Studio is in the list of allowed debugging clients. You can check it at the Zend Server GUI on Server Setup -> Debugger.
  • If you are running the script on a remote host and there's a firewall / NAT between you and the server (e.g. you are in an office LAN, trying to debug a script on a remote production machine which is not in your subnet) you'll probably need to use SSH remote port forwarding to forward connections to your PDT / Zend Studio. I won't get into how to do it right here - unless you insist.
  • If you want to only type 'php-dbg' when running instead of the full path, you can place the file in your $PATH (e.g. in /usr/local/bin) or even better, Add /usr/local/zend/bin (or /Applications/ZendServer/bin) to your $PATH - you can do that by adding the following line to ~/.bashrc:

    PATH=$PATH:/usr/local/zend/bin

Upon running the script, a debug session should simply pop-up in your PDT / Studio and you'll be able to debug. How cool is that?

BTW: This has been tested with Zend Server 4.0.0 beta1 and Zend Studio 6.1.1. It should work with other versions of Studio as well. In fact, it can also work without Zend Server as long as you have Zend Debugger installed - but why ruin a perfectly good plug?

If you improve the script or find bugs, let me know! Also, if you know how to get the same thing going with xDebug, let me know and I'll add it to the script.

Finally, it’s out: Zend Server

I normally try not to write about work related stuff... but this is a special occasion.

Zend Server is finally out for public beta. \o/

I was working so hard on this for the last year, It kind of feels like I've just crapped an Elephpant ;)

Seriously now, I really like this product. I think it has great potential. I know a bunch of very good people who worked very hard on it, and deserve every bit of gratitude. We went over some rough times at Zend and we still were able to release this wonderful product! I'm so proud... :)

Priceless: “The Issuer Certificate Is Unknown”

Firefox: "mossad.gov.il uses an invalid security certificate"

Another example of the all-so-frightening invalid HTTPS certificate warning in Firefox 3.0. I just found this one to be a bit ironic :)

BTW The Mossad website is mostly for recruiting purposes, they don't really let you search their archives on-line or anything... to bad, that could have been interesting :P

(and one more thing: yes, it's "The Mossad" and not just "Mossad" as it's frequently mis-translated in foreign media. "Mossad" literally means "Institute" or maybe in a less literal translation, "Agency". There are many institutes and agencies, but there is only one "The Institute")

Subversion: Finding the “base” revision of a branch

I use Subversion a lot - but today I've learned something new:

You can easily find the "base" revision of a branch or a tag (i.e. the revision in which the branch or tag was created) by issuing the following command:

CODE:
  1. svn log -v --stop-on-copy \
  2.     http://glista.googlecode.com/svn/branches/feature-reminders

The last revision you see in the log (in this case from one of my own Glista project's branches) is the revision the svn copy command was issued on, i.e. the branch was made.

This can then be used when merging the same branch back into trunk.

Neat!