FreeBSD, PHP and Pecl

Posted by Kevin Way Wed, 28 Feb 2007 02:55:00 GMT

I was helping move a legacy PHP app to a new server, and found it needed a PECL extension (dbx).

After installing PEAR, I got the following error:


[root@machine php]# pecl install something

Fatal error: Call to undefined function preg_match() in /usr/local/share/pear/PEAR/Frontend/CLI.php on line 70

It turns out that the problem is that within FreeBSD’s installation of PECL, it calls PHP from the command line with the -n flag. a.k.a. —no-php-ini

This prevents /usr/local/etc/php/extensions.ini from getting loaded, and thus there is no PCRE support.

You can work around it by removing “-n” from inside the pecl script.

libmap.conf -- who knew?

Posted by Kevin Way Thu, 22 Feb 2007 00:38:00 GMT

It’s not often that somebody points out FreeBSD functionality that I wasn’t already aware of, but that happened today.

We were having a problem with clamav 0.90. It would slow down, stop responding, and die, somewhere in the threading code.

Craig Green, of Sentex.net, wrote us to say that he had a similar problem with a devel version of clamav on FreeBSD, and his fix was quite unexpected.

He solved his problem by forcing clamd to use a different set of threading libraries than default. (The older “libthr”, to be precise.)

He did this by using the libmap functionality that had been added to FreeBSD in 5.1 It’s incredibly simple, you just create /etc/libmap.conf, add a few lines of configuration saying what object files to substitute, and then run your app.

In this case, he suggested:

[clamd]
libc_r.so.5             libthr.so.2
libc_r.so.6             libthr.so.2
libthr.so.2             libthr.so.2
libpthread.so.1         libthr.so.2
libpthread.so.2         libthr.so.2 

It worked perfectly. The application worked flawlessly with the older thread library.

So next time you want to use a non-standard library for just one application, remember that libmap.conf is your friend.

Now you know. And knowing is half the battle.

Shutting Apache Up in a FreeBSD Jail

Posted by Kelley Reynolds Tue, 13 Feb 2007 03:08:00 GMT

If you’ve run Apache in a FreeBSD jail, you’ve probably seen the following error messages in your error log:
     (61)Connection refused: connect to listener on 0.0.0.0:80
     (61)Connection refused: connect to listener on 0.0.0.0:80
It turns out that if you specify the Listen directive in one of the following ways:
     Listen 80
     Listen *:80
     Listen 0.0.0.0:80
it complains about connecting to the listener as previously mentioned. To make these errors disappear from the logs, all you have to do is specify the IP address of the jail like so:
     Listen jail.ip.address.here:80
and it goes away. No more error messages filling the logs.

Managing Mongrels on FreeBSD

Posted by Kevin Way Mon, 12 Feb 2007 15:00:00 GMT

Like a lot of other consultancies, we’re excited about Ruby on Rails. It provides a very nice framework to write clean, well-tested code in a great language. But hosting a production rails site isn’t quite as simple.

We run a fairly standard mix:
  • At the bottom, we have our Ruby on Rails websites.
  • They get web-enabled via Mongrel Cluster.
  • And then Apache 2.2 with mod_proxy_balancer spreads the end-users hits across the hordes of mongrels.

It works well, but there are a few problems with management. Notably, there is no FreeBSD rc.d script to easily start and stop individual sites, or to automatically start them all on boot.

As such, we quickly wrote a mongrel_cluster rc.d script that accepts a few rc.conf variables, to get your mongrel cluster running on FreeBSD in no time flat.

Configuration is simple.
  • Make a directory (/usr/local/etc/mongrel_cluster)
  • Put your mongrel_cluster yml files in that directory, naming each one for the site it represents (foo.yml bar.yml baz.yml)
Then edit your rc.conf and add the following
  • mongrel_cluster_enable=”YES”
  • mongrel_cluster_dir=”/usr/local/etc/mongrel_cluster”
  • mongrel_cluster_list=”foo bar baz”

And now put the attached mongrel_cluster file in your /usr/local/etc/rc.d directory.

Now you can do things like:

/usr/local/etc/rc.d/mongrel_cluster start to start all of your mongrel clusters at once. /usr/local/etc/rc.d/mongrel_cluster stop somesite to stop “somesite” while leaving the others running.

Hopefully that makes managing your FreeBSD mongrels just a bit simpler!

mongrel_cluster

Or see the whole file here:

#!/bin/sh
# PROVIDE: mongrel_cluster
# REQUIRE: DAEMON
# KEYWORD: shutdown
#
# Add the following line to /etc/rc.conf to enable mongrel_cluster:
# mongrel_cluster_enable (bool):      Set to "NO" by default.
#                                     Set it to "YES" to enable mongrel_cluster
# mongrel_cluster_list (str):         Set to "" by default.
#                                     The list of mongrel_cluster_list to start (leave off the .yml)
# mongrel_cluster_dir (str):          Set to "/usr/local/etc/mongrel_clusters" by default.
#
. /etc/rc.subr
PATH=$PATH:/usr/local/bin

name="mongrel_cluster" 
rcvar=`set_rcvar`
start_cmd="${name}_start" 
stop_cmd="${name}_stop" 

load_rc_config $name

eval "${rcvar}=\${${rcvar}:-'NO'}" 
[ -z "$mongrel_cluster_list" ]        && mongrel_cluster_list="" 
[ -z "$mongrel_cluster_dir" ]        && mongrel_cluster_dir="/usr/local/etc/mongrel_clusters" 
required_dirs=$mongrel_cluster_dir

# First, let's setup our start/stop routines
mongrel_cluster_start()
{
    echo "Starting Mongrel Clusters:" 
    for mongrel in $mongrel_cluster_list; do
        echo -n "   ${mongrel} -- " 
        /usr/local/bin/mongrel_rails cluster::start -C $mongrel_cluster_dir/$mongrel.yml
    done
    return 0
}

mongrel_cluster_stop()
{
    echo "Stopping Mongrel Clusters:" 
    for mongrel in $mongrel_cluster_list; do
        echo -n "   $mongrel -- " 
        /usr/local/bin/mongrel_rails cluster::stop -C $mongrel_cluster_dir/$mongrel.yml
    done
    return 0
}

# everything after the start/stop is a mongrel to be started/stopped
cmd="$1" 
if [ $# -gt 0 ]; then
    shift
fi
if [ -n "$*" ]; then
    mongrel_cluster_list="$*" 
fi

run_rc_command "${cmd}" 

Darcs, FreeBSD and AMD64. Happier Together.

Posted by Kevin Way Mon, 12 Feb 2007 14:36:00 GMT

In a previous article I wrote about a possible way to run darcs on the FreeBSD/AMD64 platform.

Sadly, it didn’t work. It nearly worked, but it did not. It’s possible the fix was simple, but I don’t know a single line of Haskell, so I didn’t bother trying.

What I did try, was the FreeBSD Linuxulator.

I compiled the kernel with:

options            COMPAT_LINUX32

and then downloaded the latest Statically linked binary for Linux/i386 from the Darcs website.

Put the darcs executable in /usr/local/bin (or wherever you prefer) then make sure FreeBSD knows what kind of executable it is by running the following:


brandelf -t Linux /usr/local/bin/darcs

Reboot and voilà! Working darcs, that seems to function not only with a small test repository, but with large, complex production repositories.

So yes, BSD-Heads, Linux is good for something after all. And yes, we are aware that this is a filthy solution, but our attempt to successfully port GHC to FreeBSD/amd64 was abandoned after it became clear that it would be very time-consuming for us, and likely very simple for somebody more familiar with the GHC build process.

Darcs, FreeBSD and AMD64. Happy Together.

Posted by Kevin Way Sat, 10 Feb 2007 19:12:00 GMT

Edit: This approach seemed tenable, but the resulting executable failed in some circumstances. We suggest you use the method in this article instead.

We recently moved to the AMD64 platform on FreeBSD, and for the most part it has been fantastic. The machines are screaming fast, and almost every piece of software we use has been supported.

Everything except darcs and ghc, which are i386 only on the FreeBSD platform.

We didn’t want to run a standard (dynamic) 32-bit binary, because then we would end up having to manage 32-bit version of the curl, readline and gmp libraries, in parallel with their 64-bit brothers. It seemed like a disaster waiting to happen at upgrade time.

After some experimentation, it became clear that the least bad solution would be to create a statically linked 32-bit binary, that could be run an i386 compatible kernel.

As such, first we built a new amd64 kernel with the following added to the kernel configuration:

options       COMPAT_IA32

Then on an FreeBSD/i386 machine, we went about building a binary package with a statically linked binary, by making a few edits to the darcs ports Makefile. Here is the diff:


--- Makefile.orig       Sat Feb 10 14:02:34 2007
+++ Makefile    Sat Feb 10 14:18:44 2007
@@ -14,10 +14,10 @@
 MAINTAINER=    haskell@FreeBSD.org
 COMMENT=       Yet another replacement for CVS, written in Haskell

-BUILD_DEPENDS= ghc:${PORTSDIR}/lang/ghc
-LIB_DEPENDS=   curl:${PORTSDIR}/ftp/curl \
-               gmp.7:${PORTSDIR}/math/libgmp4 \
-               readline.5:${PORTSDIR}/devel/readline
+BUILD_DEPENDS= ghc:${PORTSDIR}/lang/ghc \
+               curl:${PORTSDIR}/ftp/curl \
+               /usr/local/lib/libgmp.so.7:${PORTSDIR}/math/libgmp4 \
+               /usr/local/lib/libreadline.so.5:${PORTSDIR}/devel/readline

 OPTIONS=       SERVER "install server" off
 USE_AUTOTOOLS= autoconf:259
@@ -25,6 +25,7 @@
 CONFIGURE_ENV= CPPFLAGS="-I${LOCALBASE}/include ${PTHREAD_CFLAGS}" \
                LDFLAGS="-L${LOCALBASE}/lib -L${PREFIX}/lib/ ${PTHREAD_LIBS}" \
                CFLAGS="" 
+CONFIGURE_ARGS= --with-static-libs
 USE_GMAKE=     yes
 MAKEFILE=      GNUmakefile
 ALL_TARGET=    darcs darcs.1

And then, still on the i386, in ports/devel/darcs, I ran make package to create a new darcs binary package, containing the statically linked binary.

This package was then able to be copied over to the amd64 machines, and installed via pkg_add, without issue.

Edit: This binary then worked fine on a test repository, but it dumped core on a large, production repository. As such we switched to a different tactic. Read about it in Part 2.

Older posts: 1 2 3