Query your applications using IRC
IRC. Most of you know what it is. For those that don't, it stands for Internet Relay Chat - think of it as a geeky group-chat and you won't be too far off the mark.
There's a long tradition of using bots - automated processes - to provide various services in IRC channels. There are, for example, bots that help people access Paste Bin services in IRC channels so that they don't have to paste hundreds of lines of code into the channel, or there are bots which take messages for users that are currently offline then replay those messages when they come online. These bots are really useful because they simply and easily enhance a medium which is naturally used for communication without requiring any additional software to use.
Last.fm use IRC as an internal communication mechanism. They've written (and released under the GPL - thanks!) IRCCat which allows us to write simple bots to answer queries or perform commands given in IRC channels.
I've setup IRCCat and written a few simple scripts for it. It's pretty easy to get started. First you'll need to get Java and Ant setup. I'm on a Mac on OS X 10.4 so I already have Java, and MacPorts provides an Ant port which is easy to install.
After Java and Ant you'll need to clone the IRCCat source from GitHub.
git clone git://github.com/RJ/irccat.git
Now you can compile and package the bot by running ant dist
in the directory created by the git clone
.
Once it's packaged create a directory called config/
and copy the example configuration from examples/irccat.xml
there. We'll use this to setup the bot the way we want it to work.
The configuration file is reasonably well commented so open it up and run through each of the sections filling in the appropriate details.
- Provide the details of the IRC server you'd like to connect to. I use an internal server but if you don't have one then there are plenty of IRC networks out there - a quick Google should get the details.
- Tell the bot which username it should use.
- Change the external scripts hook to
scripts/run
and up the max response lines to 30. - Choose which channels you'd like the bot to join. If they don't exist them they'll be created when the bot joins them (depending on IRC network policy).
With the configuration out of the way you can now launch your bot.
ant -Dconfgfile=./config/irccat.xml
If you're in one of the channels that you've asked the bot to connect to then you should see it join. If you're not in the channel, now would be a great time to join it. You can check the bot is working properly by asking it which channels it's running in. Type !channels
into any of the channels that it's joined. It should response with a list of channels that it's currently active in.
CraigW: !channels
bot: I am in 2 channels: #foo #bar
There are a few built-in commands such as !channels
. Built-in commands always start with an exclamation mark.
Command | Description |
---|---|
!join #channel password | Make the bot join another channel. Password is optional. |
!part #channel | Make the bot leave a channel |
!channels | List all channels the bot is in |
!spam message | Send message to all channels the bot is in |
!exit | Make the bot quit IRC and shutdown |
The really interesting commands are the externals. Externals are called by starting a command with a question mark. You get to write external commands yourself and they can do anything you want.
Remember the configuration file had a cmdhandler
value that I set to script/run
? That's the first port of call for externals. I use this script to launch a router which loads and executes other commands stored in the scripts/
directory.
If you'd like to do the same thing as me, my script/run
script looks like this:
#!/bin/bash
# This script handles ?commands to irccat
exec ruby ./scripts/router "$@" 2>&1
That's executable (chmod +x script/run
). The code in script/router
looks like the following and does the routing to and invocation of the correct command.
#! /usr/bin/env ruby
COMMANDS = File.expand_path(File.dirname(__FILE__))
name, channel, username, command, arguments = *ARGV[0].split(/ /, 5)
command_script = File.join(COMMANDS, File.basename(command))
if File.exists?(command_script) && !%W(run router).include?(command)
load command_script
puts Command.execute(name, channel, username, arguments).strip
else
desired_command = "#{command} #{arguments}".strip
puts "Sorry #{name}, I don't understand `#{desired_command}`."
end
To write externals we now just need to write a short script that implements a Command
class.
The name of the file which the command should be implemented in is based on what you'd like to type into the IRC channel. If you'd like to query SNMP on a certain host under a certain OID you might like to write something like ?snmp xeriom-vm-host-06 .1.3.6.1.2.1.1.1
. The script name in this case would be script/snmp
. Here's a very simple implementation of that commands which just executes snmpwalk
and returns the results.
class Command
class << self
def execute(name, channel, username, arguments)
hostname, oid, remainder = arguments.split(/ /, 3)
`snmpwalk -c public -v 1 #{hostname}.core.xeriom.net #{oid}`
end
end
end
Now entering ?snmp xeriom-vm-host-06 .1.3.6.1.2.1.1.1
in IRC will run this script and print the results straight back into the IRC channel the command was typed in. Note that there's no need to restart the bot for changes to take effect.
CraigW: ?snmp xeriom-vm-host-06 .1.3.6.1.2.1.1.1
bot: SNMPv2-MIB::sysDescr.0 = STRING: Linux xeriom-vm-host-06.core.xeriom.net 2.6.24-17-xen #1 SMP Thu May 1 15:55:31 UTC 2008 x86_64
There's great potential in having such powerful scripts available directly in the same communication channel that you'd use to discuss development or customer relations - a simple command can quickly pull up customer records or statistics without the need to drop to the terminal and fire up the application console or load a web page.
Ruby vs Java
I've just found out that there's a Ruby port of IRCCat. I'll be swapping to use that since I find it easier to maintain and fork a Ruby project than a Java project. Your mileage may vary.
curl -LO http://barkingiguana.com/2009/03/02/query-your-applications-using-irc.html.orig
curl -LO http://barkingiguana.com/2009/03/02/query-your-applications-using-irc.html.orig.asc
gpg --verify query-your-applications-using-irc.html.orig{.asc,}
If you'd like to have a conversation about this post, email craig@barkingiguana.com. I don't bite.