Sometimes, during the recovery of a network service, it might be useful to run a script to check when the server is online again.
We can write a client that will wait for a particular network service forever or for a timeout. In this example, by default, we would like to check when a web server is up in localhost. If you specified some other remote host or port, that information will be used instead.
Listing 3.3 shows waiting for a remote network service, as follows:
#!/usr/bin/env python # Python Network Programming Cookbook -- Chapter – 3 # This program is optimized for Python 2.7. # It may run on any other version with/without modifications. import argparse import socket import errno from time import time as now DEFAULT_TIMEOUT = 120 DEFAULT_SERVER_HOST = 'localhost' DEFAULT_SERVER_PORT = 80 class NetServiceChecker(object): """ Wait for a network service to come online""" def __init__(self, host, port, timeout=DEFAULT_TIMEOUT): self.host = host self.port = port self.timeout = timeout self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) def end_wait(self): self.sock.close() def check(self): """ Check the service """ if self.timeout: end_time = now() + self.timeout while True: try: if self.timeout: next_timeout = end_time - now() if next_timeout < 0: return False else: print "setting socket next timeout %ss" %round(next_timeout) self.sock.settimeout(next_timeout) self.sock.connect((self.host, self.port)) # handle exceptions except socket.timeout, err: if self.timeout: return False except socket.error, err: print "Exception: %s" %err else: # if all goes well self.end_wait() return True if __name__ == '__main__': parser = argparse.ArgumentParser(description='Wait for Network Service') parser.add_argument('--host', action="store", dest="host", default=DEFAULT_SERVER_HOST) parser.add_argument('--port', action="store", dest="port", type=int, default=DEFAULT_SERVER_PORT) parser.add_argument('--timeout', action="store", dest="timeout", type=int, default=DEFAULT_TIMEOUT) given_args = parser.parse_args() host, port, timeout = given_args.host, given_args.port, given_args.timeout service_checker = NetServiceChecker(host, port, timeout=timeout) print "Checking for network service %s:%s ..." %(host, port) if service_checker.check(): print "Service is available again!"
If a web server, such as Apache, is running on your machine, this script will show the following output:
$ python 3_3_wait_for_remote_service.py Waiting for network service localhost:80 ... setting socket next timeout 120.0s Service is available again!
Now, stop the Apache process, run this script, and restart Apache again. The output pattern will be different. On my machine, the following output pattern was found:
Exception: [Errno 103] Software caused connection abort setting socket next timeout 104.189137936 Exception: [Errno 111] Connection refused setting socket next timeout 104.186291933 Exception: [Errno 103] Software caused connection abort setting socket next timeout 104.186164856 Service is available again!
The following screenshot shows the waiting for an active Apache web server process:
The preceding script uses the argparse
module to take the user input and process the hostname, port, and timeout, that is how long our script will wait for the desired network service. It launches an instance of the NetServiceChecker
class and calls the check()
method. This method calculates the final end time of waiting and uses the socket's settimeout()
method to control each round's end time, that is next_timeout
. It then uses the socket's connect()
method to test if the desired network service is available until the socket timeout occurs. This method also catches the socket timeout error and checks the socket timeout against the timeout values given by the user.
13.59.107.152