runningserver: hello? anybody out there?

I have created a small ruby script to check if there are running servers on a given port number. The script is able to check a list of hosts and will output an informational message on the port status for each host.

Let’s begin with the script. Then we can talk about the work it does.

Here is the code:

#!/usr/bin/ruby
##################################################################################################################
#
# runningserver.rb
# 12/DEC/2006
# etd [etd__at__nomejortu.com]
#
# Desc:
#   Script to create a connection on the specified port to check if a server is
#   listening on it.
#
# Version:
#   v1.0 [12/Dec/2006]: first released
#
###################################################################################################################
$help =<<eoh
#{$0}:
Script to create a connection on the specified port to check if a server is
listening on it.

Usage:
#{$0} [-h|-help|--help] [-p ]  [  ...]

Options:
-h/-help/--help:  This help message
-p :  Specify which TCP port should be tested.
Arguments:
host(s):  The different hosts to test.
EOH

#------------------------------ Input argument parsing
if (
ARGV.include?('--help')  ||
ARGV.include?('-help') ||
ARGV.include?('-h') ||
(ARGV.size==0)
) then
puts
puts $help
exit
end

# set the port number
if ARGV.include?('-p') then
p_position = ARGV.index('-p')
# read value after the -p
if ARGV[p_position+1] != nil then
$port = ARGV[p_position+1].to_i
else
puts "ERROR: you kind of need to specify the port if you use the -p parameter"
puts "t e.g: -p 8080nn"
exit
end
# clear these values in the array
ARGV[p_position] = nil
ARGV[p_position+1] = nil
end

# clear the ARGV of already parsed ARGs
hostlist = ARGV.compact

#------------------------------ Interesting stuff starts here
require 'socket'
require 'net/http'
require 'timeout'

if $port == nil then
$port=18264
end
#for each host in the command line
hostlist.each() do |host|
puts
serverstr = "No server was found in port #{$port}"
begin
Timeout::timeout(3) do
client = TCPSocket.open(host, $port)
client.close
serverstr = "Server is running on port #{$port}"
end
rescue Exception => e
serverstr = "No server was found in port #{$port}"
end
puts "#{host}: #{serverstr}"
end
puts

Because this is the first ruby script in this blog I will explain it step by step. The first thing that comes in the script is the input argument parsing. Input arguments are passed as a string array, in the variable ARGV. To check if the user is requesting help or usage information we can issue:

if (
ARGV.include?('--help')  ||
ARGV.include?('-help') ||
ARGV.include?('-h') ||
(ARGV.size==0)
) then
puts
puts $help
exit
end

In the same way the script checks if the user has supplied a port number. If this is not the case, we use a default port. If the input argument -p is present, we asume the next argument (p_position+1) to be the TCP port number. It is important to get the port number as an interger. We accomplish this by issuing the .to_i call.

# clear these values in the array
ARGV[p_position] = nil
ARGV[p_position+1] = nil

With the code above we clear the elements we are not using any more. Doing so we can compact the ARGV array in order to remove all the nil elements of it just by calling the .compact function of the array.

The body of the script is pretty straight forward. For each host given as input to the script we try to open a socket on the specified port. If successful, we close the socket and that’s it. To avoid hanging for ever on closed ports we are using timeout library (require 'timeout'). The timeout mechanism is very simple. You create a block and give the timeout in seconds (can be a float point value). If the block terminates before the timeout, timeout returns the value of the block. Otherwise, the exception (Timeout::Error) is raised.

begin
Timeout::timeout(3) do
#code
end
rescue Exception => e
#exception handling
end

You see? It wasn’t that difficult, was it? :)

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Slashdot
  • Technorati

Leave a Reply