Writing a custom unix style tail in PHP using Libevent API on Mac OS X 10.5.x and other platforms

Libevent is a library which provides a mechanism to execute a callback function when a specific event occurs on a file descriptor or after a timeout has been reached. Many famous applications/frameworks/libraries like memcached are using libevent. In this blog post, I will demonstrate how to write a custom unix style tail script using Libevent API in PHP.

Setting up the environment:
Setting up libevent with PHP is a little tricky. Below are the steps, I followed to make it work on Mac OSX 10.5. However the steps should be same for any other OS you choose to code on. Here we go:

  1. Check the version of libevent installed on your system. If you don’t have libevent or the installed version is < 1.4, you will need to compile libevent-1.4.x
    ~ sabhinav$ port list | grep libevent
    libevent                       @1.4.12         devel/libevent
  2. Uninstall existing libevent
    ~ sabhinav$ port uninstall libevent
  3. Add the following into your .bash_profile file:
    export MACOSX_DEPLOYMENT_TARGET=10.5
    export CFLAGS="-arch x86_64 -g -Os -pipe -no-cpp-precomp"
    export CCFLAGS="-arch x86_64 -g -Os -pipe"
    export CXXFLAGS="-arch x86_64 -g -Os -pipe"
    export LDFLAGS="-arch x86_64 -bind_at_load"
  4. Open a new terminal window. Download and extract libevent-1.4.12-stable
    ~ sabhinav$ wget http://www.monkey.org/~provos/libevent-1.4.12-stable.tar.gz
    ~ sabhinav$ tar -xvzf libevent-1.4.12-stable.tar.gz
  5. Compile libevent-1.4.12-stable
    ~ sabhinav$ cd libevent-1.4.12-stable
    ~ sabhinav$ ./configure
    ~ sabhinav$ make
    ~ sabhinav$ sudo make install
  6. Assuming you have a successful installation, lets install PECL package libevent-0.0.2.
    ~ sabhinav$ pecl download libevent-0.0.2
    ~ sabhinav$ tar -xvzf libevent-0.0.2.tgz libevent-0.0.2
    ~ sabhinav$ cd libevent-0.0.2
    ~ sabhinav$ phpize
    ~ sabhinav$ ./configure
    ~ sabhinav$ make
    ~ sabhinav$ sudo make install
  7. Enable libevent extension in your php.ini
    extension=libevent.so
  8. Reload apache server
    ~ sabhinav$ sudo apachectl restart
  9. Confirm we have libevent extension enabled using phpinfo(); or
    ~ sabhinav$ php -i | grep libevent

Writing a custom unix style tail script in PHP (tail.php)
Below is a sample script which can be used as a base for writing custom unix style tail script. Comments in the code will help you understanding the flow of the code. Also do view official documentation for PHP Libevent extension usage.

<?php

	// callback function called whenever the registered event is triggered
	function eventFd($fd, $events, $arg) {
		echo fread($fd, 4096);
	}

	// create event base
	$base_fd = event_base_new();

	// create a new event
	$event_fd = event_new();

	// resource to be monitored
	$fd = fopen($argv[1], 'r');

	// set event on passed file name
	event_set($event_fd, $fd, EV_WRITE | EV_PERSIST, 'eventFd', array($event_fd, $base_fd));

	// associate base with this event
	event_base_set($event_fd, $base_fd);

	// register event
	event_add($event_fd);

	// start event loop
	event_base_loop($base_fd);

?>

Trying out tail.php
Save the above code file and issue the following on the terminal:

~ sabhinav$ php tail.php /var/log/apache2/access_log

Try accessing a page on your webserver and you should see the access log being tailed by the php script. 😀

Enjoy!

  • Pingback: uberVU - social comments()

  • Pingback: Get real time system & server load notification on any IM using PHP and XMPP | Abhi's Weblog()

  • this doesn’t seem to be working on regular files. But it does work when the file is STDIN or a socket opened with fsockopen or any similar file descriptor like a http connection opened with fopen(“http://patchlog.com”,’r’)…

    • I am not sure if it has to do something with libevent version you have. But on my MacOSX every thing seems perfect to me. Didn’t tried elsewhere due to libevent version compatibility issues.

      Also point to note is that libevent binding of PHP seems a bit shaky to me. When a event watcher is set on a regular file, utilities like top, htop show high CPU IO cycle usage by the script.

    • I’m on Linux and this script will just exit when I run it on a regular file.
      I straced it and it seems like the epoll_ctl syscall just fails with EPERM ( permission denied ) when it tries to set polling for the file descriptor

    • I think that part can be taken care by setting right permissions on the file you want to set descriptors on and by running the tail script with enough permissions.

    • that’s what I thought too… but then I made myself root and had the same problem

    • Well I guess it’s mainly because of inconsistent php binding of libevent library. There shd be no other reason why it works on Mac and not on other OS. BTW do you have libevent-1.4 installed? I think php libevent binding works well with libevent-1.4

  • And also I think the code should be:
    event_set($event_fd, $fd, EV_READ | EV_PERSIST, ‘eventFd’, array($event_fd, $base_fd));

    because you want to be notified when you can read …

    • I am using libevent-1.4.13 on CENTOS with pecl-libevent 0.0.2 http://www.pecl.php.net/package/libevent

      The example also work fine for me on my mac.

      On CENTOS, when I used STDIN as in the examples on php.net it works. However, when I switch to a real file descriptor on CENTOS it does not work. Did anyone find a solution for this?

  • Pingback: Was ist gerade auf meinem Server los? | PHP Gangsta - Der PHP Blog()

  • Wolfgang Braun

    Well i just tried it mysql using
    – debian lenny x64
    – php 5.3.2
    – libevent 1.4.3 stable
    – libevent-0.0.2 of PECL

    Results in the same behavior Mihai already posted. Script just exits.

  • It’s more to do with libevent-0.0.2 PECL binding. I would suggest you guys to get in touch with project maintainers listed here http://pecl.php.net/package/libevent/0.0.2

    Same works for me on various platforms and yes i found it don’t work on some.

  • Kuark

    If You are looking for a nice mail “tail” php script look at:

    http://docs.homelinux.org/doku.php?id=php_mailtracer

    the script is named php mailtracer and I love it ! I can search for incoming and outgoing mail addresses with wildcards 🙂 very nice tool 🙂 and simple to install it.

    Regards

  • david
  • Pingback: 关于php的libevent扩展的应用 | 个人博客()