2009-02-05 14 views
38

मुझे यह पता लगाने का एक त्वरित तरीका है कि रूबी के साथ कोई दिया गया पोर्ट खुला है या नहीं। मैं वर्तमान में इस के साथ लगभग नगण्य रहा हूँ:रूबी - देखें कि कोई पोर्ट खुला है

require 'socket' 

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

यह बहुत अच्छा काम करता है, तो बंदरगाह खुला है, लेकिन इस बात का नकारात्मक पक्ष यह है कि कभी कभी यह सिर्फ बैठेंगे और 10-20 सेकंड के लिए प्रतीक्षा करें और फिर अंत में टाइम आउट, फेंक है ETIMEOUT अपवाद (यदि बंदरगाह बंद है)। मेरा सवाल इस प्रकार है:

क्या इस कोड को केवल एक सेकंड की प्रतीक्षा करने के लिए संशोधित किया जा सकता है (और false वापस लौटाएं यदि हमें तब तक कुछ भी नहीं मिलता है) या यह जांचने का एक बेहतर तरीका है कि किसी दिए गए होस्ट पर दिया गया पोर्ट खुला है या नहीं ?

संपादित करें: कॉलिंग बैश कोड है, जब तक यह काम करता है पार मंच (जैसे, मैक ओएस एक्स, * nix, और cygwin) के रूप में भी स्वीकार्य है, हालांकि मैं रूबी कोड पसंद करते हैं।

उत्तर

43

कुछ निम्नलिखित की तरह काम कर सकते हैं:

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

मुझे इस अवरोध (मुझे लगता है) के साथ कुछ परेशानी थी। असल में टाइमआउट वास्तव में समय समाप्त नहीं होगा। यकीन नहीं क्यों, लेकिन नेटकैट समाधान ने अपनी जगह पर अच्छी तरह से काम किया। –

+2

इस उत्तर में एक समाधान है जो विंडोज़ पर भी काम करता है: http://stackoverflow.com/a/3473208/362951 – mit

10

बस पूर्णता के लिए, बैश कुछ इस तरह होगा:

$ netcat $HOST $PORT -w 1 -q 0 </dev/null && do_something 

-w 1 1 दूसरे के एक समय समाप्ति निर्दिष्ट करती है और -q 0 का कहना है कि, कनेक्ट होने पर, कनेक्शन को बंद करें जैसे ही stdinEOF देता है (जो /dev/null सीधे करेगा)।

+1

वे बहुत सरल हैं: बस दिखाएं/dev/{tcp}/HOST/PORT फ़ाइलें हैं :) – ephemient

+2

भविष्य के संदर्भ के लिए, मैंने इसे 'नेटकैट' – HXCaine

+1

की बजाय अपने सिस्टम पर 'एनसी' के रूप में पाया चेतावनी: मैकोज़ एक्स पर, यह त्रुटि 'एनसी: अमान्य विकल्प - q' देता है। निम्नलिखित मैकोज़ एक्स और उबंटू दोनों पर काम करता है, और मेरे लिए आसान लगता है: 'एनसी-जे $ HOST $ पोर्ट' – mercurial

26

अधिक रूबी मुहावरेदार वाक्य रचना पी:

बैश भी अपने आप ही निर्मित टीसीपी/यूडीपी सेवाएं उपलब्ध हैं, लेकिन वे एक संकलन समय विकल्प हैं और मैं एक बैश उन लोगों के साथ संकलित किया है नहीं है

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

इसने इनपुट '1 9 2.0.2.0', 80, 10 के लिए झूठा सकारात्मक दिया जो अमान्य होना चाहिए (के अनुसार http://stackoverflow.com/questions/10456044/what-is-a-good-invalid-ip-address-to-use-for-unit-tests)। मुझे मैक पर रूबी 1.9.3p448 और 2.0.0p195 के साथ एक ही परिणाम मिला। इस विधि में झूठी वापसी का प्रबंधन किस तरीके से करता है? (मैंने इसे बंद करने से पहले सॉकेट को लिखने की भी कोशिश की, लेकिन वह अभी भी सच हो गया!) –

+0

बस '0.0.0.0', 80, 1 को आजमाया और यह भी सच साबित हुआ। –

+0

मेरे लिए ठीक काम करता है! – sunsations

1

मेरे क्रिस राइस के जवाब देने के लिए मामूली बदलाव। अभी भी एक ही प्रयास पर समय निकालता है लेकिन जब तक आप हार नहीं देते हैं तो कई रिट्रीज़ भी अनुमति देता है।

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 
9

मैं हाल ही में इस समाधान के साथ आया था, यूनिक्स lsof आदेश का इस्तेमाल कर रही:

def port_open?(port) 
    !system("lsof -i:#{port}", out: '/dev/null') 
end 
+2

यह मेरे लिए बहुत अच्छा था। मैं योनि में आभासी मशीनों को बंदरगाहों को आवंटित करने की एक प्रणाली शुरू करना चाहता था और यह देखने के लिए यह एक लाइनर लिखा था कि मैं जिस पोर्ट को असाइन करने वाला था, वह खुला था या नहीं: 'vms ['port'] + = 1 बंदरगाहों के दौरान। शामिल? वीएमएस ['पोर्ट'] या सिस्टम ("lsof -i: # {vms ['port']}") – Dannid

+1

यह केवल लॉग इन उपयोगकर्ता के लिए काम करता है। बोर्ड भर में काम करने के लिए, 'sudo lsof -i: ' – alpinweis

+0

का उपयोग करें, इसे काम करने के लिए मुझे '!' (ऑपरेटर नहीं) को हटाना पड़ा। –

7

अन्य सभी मौजूदा जवाब अवांछनीय है। Timeout का उपयोग discouraged है। शायद चीजें रूबी संस्करण पर निर्भर करती हैं। कम से कम के बाद से 2.0 एक बस का उपयोग कर सकते हैं:

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

पुराने के लिए गहरे लाल रंग का सबसे अच्छा तरीका मैं गैर अवरुद्ध मोड और फिर select उपयोग कर रहा है मिल सकता है। यहाँ वर्णित:

+3

मेरे लिए पूरी तरह से काम किया: 'port_is_open = Socket.tcp (होस्ट, पोर्ट, connect_timeout: 5) {true} बचाव झूठी '। आवश्यक विशिष्ट अपवादों को बचाने के लिए एक लाइनर से विस्तार करना आसान है। – anothermh

2

सभी * nix प्लेटफार्मों:

कोशिश nc/netcat आदेश का पालन।

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

-z ध्वज का उपयोग कनेक्शन शुरू करने के बजाय खुले बंदरगाहों की रिपोर्ट करने के लिए एनसी को बताने के लिए किया जा सकता है।

डब्ल्यू ध्वज जोड़ता के लिए समय समाप्ति का मतलब है और अंतिम शुद्ध पढ़ता

जी झंडा सेकंड

उपयोग -n झंडा होस्ट नाम के बजाय आईपी पते के साथ काम करने में कनेक्शन समयबाह्य है।

उदाहरण:

# `nc -z -w 1 -G 1 google.com 80` 
# `nc -z -w 1 -G 1 -n 123.234.1.18 80` 
संबंधित मुद्दे