Check if remote host is up in Python

44,588

Solution 1

This worked fine for me:

HOST_UP  = True if os.system("ping -c 1 " + SOMEHOST) is 0 else False

Solution 2

A protocol-level PING is best, i.e., connecting to the server and interacting with it in a way that doesn't do real work. That's because it is the only real way to be sure that the service is up. An ICMP ECHO (a.k.a. ping) would only tell you that the other end's network interface is up, and even then might be blocked; FWIW, I have seen machines where all user processes were bricked but which could still be pinged. In these days of application servers, even getting a network connection might not be enough; what if the hosted app is down or otherwise non-functional? As I said, talking sweet-nothings to the actual service that you are interested in is the best, surest approach.

Solution 3

HOST_UP  = True if os.system("ping -c 5 " + SOMEHOST.strip(";")) is 0 else False

to remove nasty script execution just add .strip(";")

-c 5 

to increase the number of ping requests, if all pass than True

PS. Works only on Linux, on Windows always returns True

Solution 4

I would use a port scanner. Original question states that you don't want to use a port. Then you need to specify which Protocol (Yes, this needs a port) you want to monitor: HTTP, VNC, SSH, etc. In case you want to monitor via ICMP you can use subprocess and control ping parameters, number of pings, timeout, size, etc.

import subprocess 
    try:
        res = subprocess.Popen(['ping -t2 -c 4 110.10.0.254 &> /dev/null; echo $?'],shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
        out, err = res.communicate()
        out = out.rstrip()
        err = err.rstrip()
        print 'general.connectivity() Out: ' + out
        print 'general.connectivity() Err: ' + err
        if(out == "0"):
            print 'general.connectivity() Successful'
            return True
        print 'general.connectivity() Failed'
        return False
    except Exception,e:
        print 'general.connectivity() Exception'
        return False

In case you want a port scanner

import socket
from functools import partial
from multiprocessing import Pool
from multiprocessing.pool import ThreadPool
from errno import ECONNREFUSED

NUM_CORES = 4

def portscan(target,port):
    try:
        # Create Socket
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        socketTimeout = 5
        s.settimeout(socketTimeout)
        s.connect((target,port))
        print('port_scanner.is_port_opened() ' + str(port) + " is opened")
        return port
    except socket.error as err:
        if err.errno == ECONNREFUSED:
            return False

# Wrapper function that calls portscanner
def scan_ports(server=None,port=None,portStart=None,portEnd=None,**kwargs):
    p = Pool(NUM_CORES)
    ping_host = partial(portscan, server)
    if portStart and portStart:
        return filter(bool, p.map(ping_host, range(portStart, portStart)))
    else:
        return filter(bool, p.map(ping_host, range(port, port+1)))

# Check if port is opened
def is_port_opened(server=None,port=None, **kwargs):
    print('port_scanner.is_port_opened() Checking port...')
    try:
        # Add More proccesses in case we look in a range
        pool = ThreadPool(processes=1)
                     try:
                        ports = list(scan_ports(server=server,port=int(port)))
                        print("port_scanner.is_port_opened() Port scanner done.")
                        if len(ports)!=0:
                            print('port_scanner.is_port_opened() ' + str(len(ports)) + " port(s) available.")
                            return True
                        else:
                            print('port_scanner.is_port_opened() port not opened: (' + port  +')')
                            return False
                    except Exception, e:
                        raise
                
    except Exception,e:
        print e
        raise

Solution 5

The best you can do is:

  • Try and connect on a known port (eg port 80 or 443 for HTTP or HTTPS); or
  • Ping the site. See Ping a site in Python?

Many sites block ICMP (the portocol used to ping sites) so you must know beforehand if the host in question has it enabled or not.

Connecting to a port tells you mixed information. It really depends on what you want to know. A port might be open but the site is effectively hung so you may get a false positive. A more stringent approach might involve using a HTTP library to execute a Web request against a site and see if you get back a response.

It really all depends on what you need to know.

Share:
44,588
user140736
Author by

user140736

Updated on October 23, 2021

Comments

  • user140736
    user140736 over 2 years

    How would I check if the remote host is up without having a port number? Is there any other way I could check other then using regular ping.

    There is a possibility that the remote host might drop ping packets

  • ABakerSmith
    ABakerSmith almost 6 years
    Warning. This can introduce a security flaw if the SOMEHOST comes from user input. e.g if SOMEHOST = google.com; echo "nasty command" then the users malicious command will be run after the ping finishes.
  • AmaHacka
    AmaHacka over 2 years
    ICMP requests can be blocked on remote host, so you can get HOST_UP = False when host is up.