Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby - See if a port is open

I need a quick way to find out if a given port is open with Ruby. I currently am fiddling around with this:

require 'socket'

def is_port_open?(ip, port)
  begin
    TCPSocket.new(ip, port)
  rescue Errno::ECONNREFUSED
    return false
  end
  return true
end

It works great if the port is open, but the downside of this is that occasionally it will just sit and wait for 10-20 seconds and then eventually time out, throwing a ETIMEOUT exception (if the port is closed). My question is thus:

Can this code be amended to only wait for a second (and return false if we get nothing back by then) or is there a better way to check if a given port is open on a given host?

Edit: Calling bash code is acceptable also as long as it works cross-platform (e.g., Mac OS X, *nix, and Cygwin), although I do prefer Ruby code.

like image 904
Chris Bunch Avatar asked Feb 05 '09 18:02

Chris Bunch


2 Answers

Something like the following might work:

require 'socket'
require 'timeout'

def is_port_open?(ip, port)
  begin
    Timeout::timeout(1) do
      begin
        s = TCPSocket.new(ip, port)
        s.close
        return true
      rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
        return false
      end
    end
  rescue Timeout::Error
  end

  return false
end
like image 181
joast Avatar answered Oct 14 '22 23:10

joast


All other existing answer are undesirable. Using Timeout is discouraged. Perhaps things depend on ruby version. At least since 2.0 one can simply use:

Socket.tcp("www.ruby-lang.org", 10567, connect_timeout: 5) {}

For older ruby the best method I could find is using non-blocking mode and then select. Described here:

  • https://spin.atomicobject.com/2013/09/30/socket-connection-timeout-ruby/
like image 31
akostadinov Avatar answered Oct 15 '22 00:10

akostadinov