Ruby - See if a port is open

后端 未结 7 2012
灰色年华
灰色年华 2020-12-04 14:05

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)
          


        
相关标签:
7条回答
  • 2020-12-04 14:43

    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/
    0 讨论(0)
  • 2020-12-04 14:44

    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
    
    0 讨论(0)
  • 2020-12-04 14:50

    All *nix platforms:

    try nc / netcat command as follow.

    `nc -z -w #{timeout_in_seconds} -G #{timeout_in_seconds} #{host} #{port}`
    if $?.exitstatus == 0
      #port is open
    else
      #refused, port is closed
    end
    

    The -z flag can be used to tell nc to report open ports, rather than initiate a connection.

    The -w flag means Timeout for connects and final net reads

    The -G flag is connection timeout in seconds

    Use -n flag to work with IP address rather than hostname.

    Examples:

    # `nc -z -w 1 -G 1 google.com 80`
    # `nc -z -w 1 -G 1 -n 123.234.1.18 80`
    
    0 讨论(0)
  • 2020-12-04 15:03

    My slight variation to Chris Rice's answer. Still handles timing out on a single attempt but also allows multiple retries until you give up.

        def is_port_open?(host, port, timeout, sleep_period)
          begin
            Timeout::timeout(timeout) do
              begin
                s = TCPSocket.new(host, port)
                s.close
                return true
              rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
                sleep(sleep_period)
                retry
              end
            end
          rescue Timeout::Error
            return false
          end
        end
    
    0 讨论(0)
  • 2020-12-04 15:05

    I recently came up with this solution, making use of the unix lsof command:

    def port_open?(port)
      !system("lsof -i:#{port}", out: '/dev/null')
    end
    
    0 讨论(0)
  • 2020-12-04 15:06

    More Ruby idiomatic syntax:

    require 'socket'
    require 'timeout'
    
    def port_open?(ip, port, seconds=1)
      Timeout::timeout(seconds) do
        begin
          TCPSocket.new(ip, port).close
          true
        rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
          false
        end
      end
    rescue Timeout::Error
      false
    end
    
    0 讨论(0)
提交回复
热议问题