Tech Blog :: apache

Jan 14 '12 3:55pm

How to install xhprof on OSX (Snow Leopard or Lion) and XAMPP

Note: The same instructions apply to XDebug and possibly every other PECL module in this environment.

XHProf is a very neat PHP profiler. Documentation and general installation instructions are not hard to come by, but none of the examples I found had the right steps for my particular setup, Mac OSX Lion with XAMPP running php 5.3. (Should apply also to OSX Snow Leopard.) So this post fills in that hole; for everything else regarding xhprof look elsewhere.

The problem is the "architecture" that xhprof compiles to; OSX and xhprof are 64-bit but XAMPP is apparently 32-bit. (If you're using MAMP instead of XAMPP, you'll have a similar problem; here is a solution for that.)

After trying multiple variations, the solution that worked was adapted from this memcached-on-xampp post):

  1. Download the latest copy of xhprof
  2. sudo phpize (not sure if this is actually necessary. You may run into problems here; find the solution to that elsewhere.)
  3. If you've been trying other methods that failed, clean up the old junk: sudo make clean
  4. The most important part:
    sudo MACOSX_DEPLOYMENT_TARGET=10.6 CFLAGS='-O3 -fno-common -arch i386 -arch x86_64' LDFLAGS='-O3 -arch i386 -arch x86_64' CXXFLAGS='-O3 -fno-common -arch i386 -arch x86_64' ./configure --with-php-config=/Applications/XAMPP/xamppfiles/bin/php-config-5.3.1
  5. sudo make
  6. sudo make install
  7. Add to your php.ini:
    extension =
    xhprof.output_dir = "/Applications/XAMPP/xhprof-logs"

Then run php -i | grep xhprof and if it worked, it should tell you which version you're running. If it fails, it will say, mach-o, but wrong architecture in Unknown on line 0.

Good luck!

Update: It's worth mentioning, you'll probably also need to install Graphviz so xhprof can find the dot utility to generate graphics.

Mar 30 '11 2:41pm

Quick tip: Extract all unique IP addresses from Apache logs

Say you wanted to count the number of unique IP addresses hitting your Apache server. It's very easy to do in a Linux (or compatible) shell.

First locate the log file for your site. The generic log is generally at /var/log/httpd/access_log or /var/log/apache2/access_log (depending on your distro). For virtualhost-specific logs, check the conf files or (if you have one active site and others in the background) run ls -alt /var/log/httpd to see which file is most recently updated.

Then spit out one line to see the format:
tail -n1 /var/log/httpd/access_log

Find the IP address in that line and count which part it is. In this example it's the 1st part (hence $1):

cat /var/log/httpd/access_log | awk '{print $1}' | sort | uniq > /var/log/httpd/unique-ips.log

You'll now have a list of sorted, unique IP addresses. To figure out the time range, run
head -n1 /var/log/httpd/access_log
to see the start point (and the tail) syntax above for the end point.)

To count the number of IPs:
cat  /var/log/httpd/unique-ips.log | wc -l

To paginate:
more  /var/log/httpd/unique-ips.log

Have fun.

Nov 13 '09 3:09pm

Old-school SSI on PHP5/Apache2.2

I had to set up a local copy of an old site running (on the server) PHP 4 and hundreds of old-school SSIs (server-side includes), of the <!--#include variety. It took a bunch of time to get it right, but in the end it's pretty simple:

      Make sure mod_include is enabled in your httpd.conf.
      Have this directive in your httpd.conf (it should be possible in the virtualhost or .htaccess too but doesn't work there:
      <Directory />
      Options Includes
      (It's possible the Directory can be other than root (/) -- I think the key is just to put it in httpd.conf.)
      Also in httpd.conf, put the directive SetOutputFilter INCLUDES.

Prior to PHP 4.6 I think, there was a configuration directive --enable-track-vars which allowed SSI variables to work PHP, or something like that, but it's deprecated and built in now, so PHP can output SSI directives.

Make sure to restart Apache after adding this, of course.

If I run into other issues with this, I'll update this post; in the meantime, it seems to be working.

Oct 26 '09 11:40pm

Setting Apache environment variables with mod_rewrite

Apache's mod_rewrite module is most commonly used to generate clean URLs, by covertly "rewriting" incoming paths to different internal paths. (Drupal rewrites /some/url as index.php?q=some/url and works off the querystring, for example.) It can also be used to overtly redirect users with the same kind of rules. But mod_rewrite's flexibility allows it to be used for a whole lot more than simple URL handling. Regex patterns can be tested to set environment variables, for example (the kind retrieved with PHP's getenv(). I recently started using rewrite rules in my Drupal root .htaccess files as an alternative to my Environments module, for organizing all my server- and subdomain-differentiated logic in a central location. This functionality is documented reasonably well at; see the "Documentation" section at the bottom. Here are some examples I'm using. They're all wrapped in:
<IfModule mod_rewrite.c>
  RewriteEngine On
This sets environment variables for each server environment:
  ## set env vars for domains
  ## dash indicates no subst
  ## '.*' (any string) is critical!! thanks
  #  siteenv = local, live, dev
  RewriteCond %{SERVER_NAME} ben.local
  RewriteRule .* - [E=siteenv:local]
  RewriteCond %{SERVER_NAME} ^$ [OR]
  RewriteCond %{SERVER_NAME} ^$
  RewriteRule .* - [E=siteenv:live]
  RewriteCond %{SERVER_NAME} ^$
  RewriteRule .* - [E=siteenv:dev]
Uncomment this for debugging:
## stop all following rules on local (for debugging)
##  RewriteCond %{ENV:siteenv} local
##  RewriteRule .* - [L]
This rule redirects to It excludes my local and dev sites, redirects ([R]), and stops checking for other rules ([L]):
  # tech home
  RewriteCond %{SERVER_NAME} ^tech.benbuck
  RewriteCond %{ENV:siteenv} !local
  RewriteCond %{ENV:siteenv} !dev
  RewriteRule ^$ [R,L]
This powers the "shortcut" URLs which I use to tweet my posts. !-f and !-d exclude valid file and directory paths, respectively.
  RewriteCond %{SERVER_NAME} ^$ [OR]
  RewriteCond %{SERVER_NAME} ^$
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule ^b/([0-9]*)/?$$1  [L]
On a multi-site setup, RewriteRules can send /files to /sites/somesite/files based on the subdomain. (This only works for HTTP-requested paths, however; unlike symlinks, these rules have no effect on include()'d paths, for instance.) The next thing I'd like to try is virtual document roots (*.domain) that map to different folders. If you have any other cool mod_rewrite tips, or see any errors in my examples here, please post a comment!