1
Nov
2011

Checking JMX with JRuby

I’ve recently been playing around with JRuby and found the switch from MRI to be hassle free. One of the advantages of JRuby is it’s portability. You can use nearly all Ruby code straight away on the JVM without having to do any code changes, you just include the jruby jar in your classpath.

Another advantage is Java interoperability from JRuby (just require ‘java’). I’ve found this useful when using JMX to check certain conditions are in place while performing releases and for general monitoring.

The following script uses JRuby’s Java integration to walk a given ObjectName’s attributes within JMX.

require 'java'

# Return a JMX Connection
def connect_to_jmx service_url, credentials
	jmxUrl = javax.management.remote.JMXServiceURL.new(service_url)

	environment = java.util.HashMap.new
	environment.put(javax.management.remote.JMXConnector.CREDENTIALS, 
                              credentials.to_java(:string))

	jmxCon = javax.management.remote.JMXConnectorFactory.connect(jmxUrl, 
                                                                                              environment)
	return jmxCon.getMBeanServerConnection
end

# Walk the JMX tree and return the attributes.  Optionally limit to a single ObjectName
def walk_tree jmx_connection, limited_to=''
	names = jmx_connection.queryNames(
                                           javax.management.ObjectName.new(limited_to), nil)

	cached = Hash.new([])

	names.each do |name|
	   info = jmx_connection.getMBeanInfo(name)
	   info.getAttributes.each do | mbi|
		   attr = jmx_connection.getAttribute(name, mbi.getName)
		   cached.store(name.getCanonicalName, 
                          cached[name.getCanonicalName] << { mbi.getName  => attr })
	   end     
	end
	
	return cached
end

service_url = 'host:port'
credentials = ['username', 'password']
jmx_connection = connect_to_jmx(service_url, credentials)

results = walk_tree(jmx_connection, 'java.lang:type=OperatingSystem')

results.each do | key, attributes |
  puts ' * ' + key
  attributes.each do | attr |
	puts " ** #{attr.first[0]} :: #{attr.first[1]}"
  end
  puts
end

When invoked against a running JMX instance this will return something similar to:

 
> jruby jmx_walker.rb
 * java.lang:type=OperatingSystem
 ** FreePhysicalMemorySize :: 51955511296
 ** TotalPhysicalMemorySize :: 151873998848
 ** Name :: Linux
 ** Arch :: amd64
 ** Version :: 2.6.18-194.11.4.el5
 ** AvailableProcessors :: 24
 ** SystemLoadAverage :: 0.49

Hopefully this is of use to you, or inspires you to investigate JRuby a bit further. I’d highly recommend it for Java shops who want to take advantage of Ruby’s scripting ability.

1
Mar
2011

Start a web server from your pwd using Ruby and Thin

Occasionally I’m interested in grabbing files from a directory on a remote host. This could be for another process to consume or to look at on my local work station.

The standard way of doing this is using scp, ftp or a file share. I prefer to start a short-lived web server that shares the file system.

To make this simple I use a ruby script to allow me to start a webserver from the directory I’m currently in.

 
['rubygems', 'thin', 'rack', 'socket'].each {|file| require file }
Thin::Server.start(IPSocket.getaddress(Socket.gethostname), 7777) do
  use Rack::CommonLogger
  run Rack::Directory.new(Dir.pwd)
end

As an alias for ~/.bashrc it looks like this:

 
alias rshare="ruby -rubygems -e \"['thin', 'rack', 'socket'].each {|file| require file };"\
" Thin::Server.start(IPSocket.getaddress(Socket.gethostname), 7777) {"\
" use Rack::CommonLogger; run Rack::Directory.new(Dir.pwd) }\""

This allows you to go to port 7777 on the host and retrieve the files you’re interested in.

@joejag /tmp $ rshare
>> Thin web server (v1.2.7 codename No Hup)
>> Maximum connections set to 1024
>> Listening on 10.0.0.2:7777, CTRL+C to stop
10.0.0.8 - - [01/Mar/2011 07:45:15] "GET / HTTP/1.1" 200 2153 0.0038

You will need to have the ‘thin’ and ‘rack’ gems installed to do this.

7
Aug
2009

Using Ruby to parse an Excel document

If you work in the finance domain you are often confronted with data in spreadsheets. I’ve used a number of ways to read spreadsheets before like Scriptom (Groovy) or POM (Java). Ruby comes with a windows specific OLE bridge which allows you to use COM to communicate with a number of different MS applications. The pickaxe has more details.

Here is a 4 line working example of opening an Excel document, choosing a worksheet then printing the values of a range:

require 'win32ole'
excel = WIN32OLE::new('excel.Application')
sheet = excel.Workbooks.Open('c:\excel.xls').Worksheets('worksheet')
sheet.Range('A1:A3').columns.each { |col| col.cells.each { |cell| puts cell['Value'] } }
3
Jul
2009

Using Ruby as an AWK replacement

Someone at work asked if you could use Ruby like AWK.  I did a little digging and found that you can.

cat file | ruby -n -a -e 'puts "#{$F[0] $F[1]}"'

‘-n’ makes the Ruby iterate over all lines successively assigning them to $_
‘-a’ makes Ruby split $_ into its parts assigning the result to $F which is an array of strings
‘-e’ means that what follows is code to be executed.
‘-F’ specifies the column separator

I performed a speed comparison on some different size files and operations. For files under 500kb lines Ruby has comparable performance to AWK. For anything larger then Ruby (1.8.6) is at best twice as slow. Though I wouldn’t expect a general purpose language to outperform a specialist tool.