How to Find and Kill a Rogue Server Process

What do you do when you cannot start a new server session because the address is already in use? It happens to the best of us, such as this morning when I exited my terminal without first quitting the rails server. I found myself faced with this error in my new terminal when trying to spool up a localhost:

 ? ./script/server => Booting WEBrick => Rails 2.3.11 application starting on http://0.0.0.0:3000 => Call with -d to detach => Ctrl-C to shutdown server [2011-12-22 11:41:15] INFO  WEBrick 1.3.1 [2011-12-22 11:41:15] INFO  ruby 1.8.7 (2011-02-18) [i686-darwin10.7.0] [2011-12-22 11:41:15] WARN  TCPServer Error: Address already in use - bind(2) Exiting

I Googled around for some information, but ultimately Paul was able to troubleshoot my issue over corp chat. Here’s the solution that worked:

Enter this into the terminal:

 lsof -i TCP:3000

It will yield a result that might look something like this:

 renaebair@siren ~/workspace/intridea/newsite (master)  ? lsof -i TCP:3000 COMMAND  PID   USER       FD     TYPE     DEVICE     SIZE/OFF    NODE   NAME ruby   68780   renaebair   6u    IPv4     0x10898278     0t0      TCP     *:hbci (LISTEN)

Grab the process number (a.k.a. PID) (in this case it was 68780) and then type “kill #{that_pid}”:

 kill 68780

Then try restarting your server and all should be well!

Paul here with a few quick words about what’s going on in this case:
When Renae closed her terminal session with the rails server still running, the server process became orphaned. It was still active and serving pages on localhost:3000, but without a controlling terminal window, Renae was not sure how to stop it. Also, because it was bound to port 3000 it prevented a new rails server from starting on the same port. The lsof command is used to list open files, in this case the pseudo-file for tcp port 3000. (It can also be used to figure out what processes are logging to a file lsof log/development.log. This is sometimes useful when a plugin is writing to the rails log instead of its own log file.)

Once we have the PID for Renae’s orphaned process, we can send a signal to it, telling it to close itself. The kill command is the mechanism for sending that signal. To be polite, we first send a TERM signal, which roughly means, “Would you please finish up what you’re doing and close, dearie?” If that doesn’t work in a reasonable time, we can send a KILL signal (side note: I find it unfortunate that the signal and the command share a name, but that precedent is older than I am) kill -9 some_pid which translates to “KILL IT WITH FIRE”. As in real life, being less polite may result in needing to handle some cleanup yourself.

There is a slightly easier option. If we suspect that port 3000 is bound to a rogue rails process, you can use the killall command as a more “shotgun” approach. But what fun is that?