Gersham Meharg's Blog

tr.im Launched


posted September 05, 2008 00:53 ago by gersham


A new project I'm involved with called tr.im has been launched.

It's a URL shortener service that is pretty slick, allowing you to do a one click URL trim and then tweet to Twitter. Check it out!


Monit Configuration Example


posted May 05, 2008 11:23 ago by gersham


Monit is an excellent utility that I use to ensure the health of my Mongrel processes, my webserver, mailserver and other proceses. Should a process fail it'll be restarted. Should the system consume too much memory or have too high a load I'll receive notification emails. It's great. Highly suggested for any Rails install.

Download and install monit (part of the package management system with most distributions), then edit the email addresses, username and password below and place the contents inside /etc/monit/monitrc, restarting monit afterwards.


set daemon  60
set logfile syslog facility log_daemon
set mailserver localhost
set mail-format { from: alert@example.com }
set alert recipient@example.com

set httpd port 7999 and
   allow username:password

check system meharg.com
   if loadavg (1min) > 4 then alert
   if loadavg (5min) > 3 then alert
   if memory usage > 95% then alert
   if cpu usage (user) > 95% then alert

check process nginx with pidfile /var/run/nginx.pid
   group www-data
   start program  "/etc/init.d/nginx start"
   stop program  "/etc/init.d/nginx stop"
   if failed host meharg.com port 80 protocol http
      and request "/" then alert
   if cpu is greater than 60% for 2 cycles then alert
   if cpu > 90% for 5 cycles then restart
   if children > 50 then restart
   if loadavg(5min) greater than 10 for 8 cycles then alert
   if 3 restarts within 5 cycles then timeout

check process mysql with pidfile /var/run/mysqld/mysqld.pid
   group mysql
   start program = "/etc/init.d/mysql start" 
   stop program = "/etc/init.d/mysql stop"
   if failed host 127.0.0.1 port 3306 then restart
   if 5 restarts within 5 cycles then timeout

check process mongrel_3000 with pidfile /var/www/apps/meharg.com/tmp/pids/mongrel.3000.pid
   group mongrel
   start program = "/usr/bin/mongrel_rails start -d -e production -a 127.0.0.1 -c /var/www/apps/meharg.com/ --user mongrel --group mongrel -p 3000 -P /var/www/apps/meharg.com/tmp/pids/mongrel.3000.pid -l /var/www/apps/meharg.com/log/mongrel.3000.log"
   stop program = "/usr/bin/mongrel_rails stop -P /var/www/apps/meharg.com/tmp/pids/mongrel.3000.pid"
   if failed host 127.0.0.1 port 3000 protocol http
      and request "/" then alert
   if totalmem > 100 Mb then restart
   if cpu is greater than 60% for 2 cycles then alert
   if cpu > 80% for 5 cycles then restart
   if loadavg(5min) greater than 10 for 8 cycles then restart
   if 3 restarts within 5 cycles then timeout

check process mongrel_3001 with pidfile /var/www/apps/meharg.com/tmp/pids/mongrel.3001.pid
   group mongrel
   start program = "/usr/bin/mongrel_rails start -d -e production -a 127.0.0.1 -c /var/www/apps/meharg.com/ --user mongrel --group mongrel -p 3001 -P /var/www/apps/meharg.com/tmp/pids/mongrel.3001.pid -l /var/www/apps/meharg.com/log/mongrel.3001.log"
   stop program = "/usr/bin/mongrel_rails stop -P /var/www/apps/meharg.com/tmp/pids/mongrel.3001.pid"
   if failed host 127.0.0.1 port 3001 protocol http
      and request "/" then alert
   if totalmem > 100 Mb then restart
   if cpu is greater than 60% for 2 cycles then alert
   if cpu > 80% for 5 cycles then restart
   if loadavg(5min) greater than 10 for 8 cycles then restart
   if 3 restarts within 5 cycles then timeout

check process mongrel_3002 with pidfile /var/www/apps/meharg.com/tmp/pids/mongrel.3002.pid
   group mongrel
   start program = "/usr/bin/mongrel_rails start -d -e production -a 127.0.0.1 -c /var/www/apps/meharg.com/ --user mongrel --group mongrel -p 3002 -P /var/www/apps/meharg.com/tmp/pids/mongrel.3002.pid -l /var/www/apps/meharg.com/log/mongrel.3002.log"
   stop program = "/usr/bin/mongrel_rails stop -P /var/www/apps/meharg.com/tmp/pids/mongrel.3002.pid"
   if failed host 127.0.0.1 port 3002 protocol http
      and request "/" then alert
   if totalmem > 100 Mb then restart
   if cpu is greater than 60% for 2 cycles then alert
   if cpu > 80% for 5 cycles then restart
   if loadavg(5min) greater than 10 for 8 cycles then restart
   if 3 restarts within 5 cycles then timeout


Nginx Configuration File


posted May 04, 2008 11:13 ago by gersham


A friend was asking for configuration instructions for Nginx so I thought I'd post it up here for reference (for myself even).

Nginx is the 6th most popular webserver on the Internet and serves up over a million domains. (Wikipedia).

It's easy to configure and a heck of a lot more light weight than Apache. For most web hosting and proxying requirements it's a pretty good choice. I do most of my Rails hosting through an Nginx proxy to a cluster of mongrel servers.

First you'll need to download and install Nginx, it's available within the package management system of Ubuntu and other distributions.

On Ubuntu there's a directory created by the default install called /etc/nginx/sites-enabled/ which you can place Nginx config files in. If you don't have this include config line in your /etc/nginx/nginx.conf you'll need to create it.

For instance, for this site I use the following in the contents of /etc/nginx/sites-enabled/meharg.com



upstream meharg.com_mongrel {
        server 127.0.0.1:3000;
        server 127.0.0.1:3001;
        server 127.0.0.1:3002;
}

upstream meharg.com_apache_svn {
        server 127.0.0.1:2999;
}

server {
        listen   80;
        server_name  meharg.com www.meharg.com;

        access_log  /var/log/nginx/meharg.com.access.log;

        #
        # Deny .SVN files
        #

        location ~ /\.svn {
                deny  all;
        }

        #
        # Serve static files directly
        #

        location ~ ^/(images|javascripts|stylesheets)/ {
                root /var/www/apps/meharg.com/public;
                #access_log        off;
                expires           30d;
        }

        # 
        # All the rest to the mongrel cluster
        #

        location / {

                proxy_set_header   Host             $host;
                proxy_set_header   X-Real-IP        $remote_addr;
                proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;

                proxy_pass  http://meharg.com_mongrel;
        }
}



CEDICT for WeDict on the iPhone


posted April 28, 2008 09:50 ago by gersham


If you have an iPhone and you're learning Chinese you've got a problem. There's no dictionaries for the iPhone (jailbroken of course) that support English to Pinyin. They're all Engish to Chinese characters. This is fine of course if you're a Chinese speaker, but for us noobs learning Chinese it can be frustrating.

Seeing that WeDict (a jailbroken iPhone dictionary application) supported StarDict and having some experience with the CEDICT I set out to see if I could convert the CEDICT to StarDict (I wasn't able to find any CEDICT StarDicts on the Internet, perhaps someone else has done this before and my GoogleFu failed).

The result is this. It's an english to pinyin dictionary with simplified Chinese characters inclued. It's an archive containing three files: "english-pinyin.dict.dz", "english-pinyin.idx", and "english-pinyin.ifo". First install WeDict from Installer. Once that's done, these three files can be "tar xvfz"ed and copied to your iphone /var/Library/WeDict folder (use FTP or SCP to do so) and you're ready to go.

The dictionary isn't too bad, the accuracy of the words in most cases is pretty good. One issue is that it's not always obvious which of the multiple translations to use. However it's an invaluable aid to those with iPhone's learning Chinese.

Permission is given to modify and redistribute under terms of the original CEDICT license.

English to Pinyin WeDict Files


SMS Parsing Script for the iPhone


posted April 19, 2008 06:30 ago by gersham


Here's a wacky little script that connects to your iPhone through SSH, downloads its SMS database and spits out the result on standard out as an XML file. I've been planning to get around to wrapping this in an Applescript application for easy display but have been bogged down in other things. Perhaps someone else will find this of use:

Place this in a Ruby script of some sort:



#!/usr/bin/env ruby

require 'rubygems'
require 'sqlite3'
require 'builder'

# Connect and grab the db from the iphone, it needs to be WIFI connected
# It needs SSH key authentication setup for passwordless access
# It needs the host named iphone set to it's IP address in /etc/hosts

# Test the connection
system "ping -o -t 3 iphone > /dev/null"
if $? != 0
  puts "Can not connect to the iphone!"
  exit 1
end

# Copy over the database
system "scp -q iphone:/var/mobile/Library/SMS/sms.db /tmp/sms.db"

# Connect to the SMS database 
db = SQLite3::Database.new('/tmp/sms.db')
db.results_as_hash = true

# Messages XML
messages = Builder::XmlMarkup.new()

messages.instruct!
messages.messages {

  # Received Messages
  messages.received {
    db.execute("SELECT * FROM message WHERE flags = 2") do |message|
      messages.message { messages.sender message[1]
                         messages.time Time.at(message[2].to_i)
                         messages.text message[3] }
    end
  }

  # Sent Messages
  messages.sent {
    db.execute("SELECT * FROM message WHERE flags = 3") do |message|
      messages.message { messages.recipient message[1]
                         messages.time Time.at(message[2].to_i)
                         messages.text message[3] }
    end
  }

}

puts messages.to_s

# Remove the database locally
system "rm /tmp/sms.db"
exit 0



Making your iPhone a bit easier to get to


posted April 11, 2008 12:29 ago by gersham


I'm doing quite a bit of hacking with the iPhone and for convenience sake I need to get to it through the terminal on a regular basis. Here's some tips for making this much smoother and more secure for accessing it.

  1. Install a SSH daemon on the iPhone using installer.
  2. Edit your DHCP server on your local wireless network to always assign the same IP address to the iPhone (most Linksys, DLink, etc support this, you'll need the mac address of the iPhone which you can infer from "arp -an" on your command line).
  3. Add that IP address and hostname to your /etc/hosts, something like:

    10.0.1.111 iphone

  4. Edit your local ~/.ssh/config file to make root the default user to SSH to the iPhone:

    Host iphone user root

  5. Make an .ssh directory on the iPhone:

    ssh iphone mkdir /var/Root/.ssh

  6. scp your ssh public key to the iphone:

    scp ~/.ssh/id_dsa.pub iphone:/var/Root/.ssh

  7. Fix the remote permissions:

    ssh iphone chmod -R 700 /var/Root/.ssh

There you go, you should now be able to SSH to your iPhone with ease. I'd suggest also getting bossprefs and turning off SSH when it's not in use, otherwise you could set SSHd to only do key authentication, not password (I haven't tried this so it may not work). Don't change the root password on the iPhone, some versions can get really messed up by doing this forcing you to reinstall the iPhone OS.