Tequila Fish Ran-dumb ramblings of me…


Installing Bundler for Ruby in Ubuntu 10.04

When attempting to install Bundler for Ruby on Ubuntu 10.04, I got the following error:

shell> sudo gem install bundler
ERROR: Error installing bundler:
bundler requires RubyGems version >= 1.3.6

Running sudo gem -v I saw that I had 1.3.5. To get around this, simply install the available updater gem, then run it:

shell> sudo gem install rubygems-update
shell> sudo /var/lib/gems/1.8/bin/update_rubygems

Now running gem -v I see that I have 1.8.15 and I am able to install bundler:

shell> gem install bundler
Fetching: bundler-1.0.21.gem (100%)
Successfully installed bundler-1.0.21
1 gem installed
Installing ri documentation for bundler-1.0.21...
Installing RDoc documentation for bundler-1.0.21...


Unix: Delete all but N most recent files in a directory

Here's a handy little command to delete every file in a directory except for the N most recent files. It is helpful for including in a log rotation or db backup script.

find /path/to/files/ -maxdepth 1 -type -f -name '*' -print0 | xargs -r0 ls -t | tail -n +5 | tr '\n' '\0' | xargs -r0 rm

Breaking down and explaining each section of the command, we have:

find /path/to/files/ -maxdepth 1 -type -f -name '*' -print0

This will list all files in the specified directory. The reason we use 'find' rather than 'ls' is because we need the full path of the files when later passing the argument list to the 'rm' command. We specify a 'maxdepth' so we only search within the current directory. We also specify a 'type' of 'f' so that we only find files and not other items like directories, sockets, or symbolic links. It's probably best not to use '*' as your 'find' expression, as it could be dangerous if you accidentally point it to the wrong directory. Use something like '*.sql.gz' or '*.log' or whatever suits you. Also note that we are using '-print0' so that the subsequent commands will be able to handle spaces and other special characters in filenames (see http://en.wikipedia.org/wiki/Xargs#The_separator_problem)

xargs -r0 ls -t

This will sort the list returned by the 'find' command in descending order by timestamp (newest to oldest). The '-r' parameter instructs xargs not to run of no files are found by the first 'find' command. The '-0' parameter gets around the separator problem described in the previous step.

tail -n +5

This will filter the list to only show from the 5th line onward. So if you want to keep the 10 most recent files, use +10 as your argument.

tr '\n' '\0'

This is similar to using '-print0' with the 'find' command above. We need to clean up the output so that the subsequent xargs command can handle potential spaces in the filenames. So we use the 'tr' command to translate newlines to the null character.

xargs -r0 rm

Finally, this command will delete the files returned by the combination of the previous commands.


MySQL: Dynamic ORDER BY clause

When developing some discography software for a website, I came across the need to sort a list of releases differently depending on their release date. I wanted to sort future releases in ascending order (oldest to newest) and sort past releases in descending order (newest to oldest). This isn't an easy task, but after many hours of trial and error, I finally figured it out with some MySQL trickery.

Given the following MySQL Database table named releases:

| Field       | Type             | Null | Key | Default | Extra          |
| id          | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| title       | varchar(256)     | NO   |     | NULL    |                |
| releasedate | date             | NO   |     | NULL    |                |

I accomplished the dynamic ORDER BY clause by using the following query:

       UNIX_TIMESTAMP(releasedate) AS releasedate_unix, 
       CASE WHEN releasedate > NOW() THEN 0 ELSE 1 END AS futureorpast
FROM releases
ORDER BY futureorpast ASC, 
         CASE WHEN releasedate_unix > UNIX_TIMESTAMP(NOW()) THEN 
            (releasedate_unix * -1) 

Now for an explanation. First, we need to "seperate" the results into two sets: future releases and past releases. This is accomplished by calculating the futureorpast column upon which we can sort, so future releases are assigned a value of 0 while past releases are assigned a value of 1. These are then sorted with future releases coming first, because obviously 0 comes before 1.

Next comes the tricky part: we want to sort future releases by ASC but past release by DESC. This is unable to be accomplished using dynamic ASC/DESC in a CASE clause because you can only calculate values using CASE, not clauses. The trick then is to convert the date column into a unix timestamp so that we have an integer, and then take the inverse of that integer on the values we want to sort in reverse.

Using this technique I was able to sort a subset of results in one direction and another subset of the same results in a different direction. I'm not sure if this is the best way to accomplish this, so if anyone has other suggestions on how to accomplish this, I'd love to hear them!

Tagged as: , , , 1 Comment

How to increase bash shell history length in OS X

I do a lot of command line work on my OS X machine, so the history saves me a lot of time running repeat commands and also refreshing my memory on commands that I haven't run in a while. Unfortunately, the default history length in OS X is 500 commands. That seems like a lot, but when you're running 50+ commands a day it can push older commands off the list pretty quickly. This is easily solved by setting the HISTFILESIZE in your .bash_profile file.

First, to find out what HISTFILESIZE is currently set at, run the following command from Terminal:


To change this value, simply add the following line to your .bash_profile file (found in /Users/yourname/):


This increases your bash history to 2000 items. It will take effect next time you open a Terminal window.


eAccelerator and open_basedir: open_basedir restriction in effect. File() is not within the allowed path(s):

After installing eAccelerator on a CentOS 5.5 server running PHP 5.2.10, a bunch of websites began failing with open_basedir errors like so:

[Fri Jul 16 17:53:50 2010] [error] [client XX.XX.XXX.XXX] PHP Warning: require() [function.require]: open_basedir restriction in effect. File() is not within the allowed path(s): (/home/username/) in /home/username/public_html/wp-settings.php on line 19, referer: http://www.server.com/

After doing some research it turns out that a default option that is compiled into eAccelerator is incompatible with open_basedir. The fix is easy enough, simply re-compile with the --without-eaccelerator-use-inode option like so:

make clean
./configure --without-eaccelerator-use-inode
make install

After re-compiling and installing, make sure you clear out the existing eAccelerator files before restarting Apache:

rm -rf /var/cache/eaccelerator/*
apachectl restart

eAccelerator states that the next version will have this compile option set by default.


Filed under: CentOS, Linux, PHP, Tech 1 Comment

MySQL: Global find & replace

Global find & replace is easy in MySQL:

UPDATE table_name SET column_name = replace(column_name, "searchString", "replaceString");


OS X Snow Leopard Bugs: Audio gets reset to mute on reboot.

While my upgrade to OS x 10.6 Snow Leopard has been mostly smooth, there are a few annoying bugs I've come across. This one has to do with audio - upon reboot, audio gets set to mute no matter what settings I had the volume on before. Not a big problem, but annoying none the less. Here's how to fix it:

  1. In Finder, navigate to Macintosh HD > Library > Preferences > Audio
  2. Delete the following files:
    •      com.apple.audio.DeviceSettings.plist
    •      com.apple.audio.SystemSettings.plist
  3. Open System Preferences > Sound
  4. Set your sound to your preferred settings
  5. Exit System Preferences and Reboot

There you go! After deleting those files, they will be re-created when you go into System Preferences and your audio will no longer be muted upon reboot.

Filed under: Apple, OS X, Tech 2 Comments