ping multiple Ips with python

.d.hos dhostetler at sopris.net
Mon Jan 6 19:59:13 CET 2003


Gerhard Haering <gerhard.haering at gmx.de> wrote in message news:<mailman.1041650767.29913.python-list at python.org>...
> * darrell <dgallion1 at yahoo.com> [2003-01-04 03:07 +0000]:
> > Multiple ping sounded like fun.
> 
> Indeed :)
> 
> > So here's a quick mod to some ping code I found.
> 
> I'll try to look at it. I've meanwhile come up with this piece of code
> (unfortunately I can't sucessfully kill the pings, the os.kill only kills the
> 'sh' processes from popen2.Popen3:
> 
> If nothing else, the original poster might benefit from the example of using
> Queue.Queue with *one* database logger thread.
> 
> #v+
> import threading
> import os, popen2, select, signal
> import Queue
> import time
> 
> from pyPgSQL import PgSQL
> 
> # (PostgreSQL) database schema:
> # CREATE TABLE LOG(ADDRESS INET, UP BOOL);
> 
> HOST_UP = 1
> HOST_DOWN = 0
> 
> PING_INTERVAL = 5
> 
> def log(s):
>     print s
> 
> class Pinger(threading.Thread):
>     def __init__(self, queue, address, *args, **kwargs):
>         self.address = address
>         self.queue = queue
>         threading.Thread.__init__(self, *args, **kwargs)
>         self.stop = 0
> 
>     def run(self):
>         child = popen2.Popen3("ping -i %i %s 2>&1" % (PING_INTERVAL, self.address))
>         log("started child %i" % child.pid)
>         while 1:
>             ready_fds = select.select([child.fromchild], [], [])
> 
>             line = child.fromchild.readline()
>             if line.find("Host is down") >= 0:
>                 log("host %s is down" % self.address)
>                 self.queue.put((self.address, HOST_DOWN))
>             else:
>                 log("host %s is up" % self.address)
>                 self.queue.put((self.address, HOST_UP))
>             
>             if self.stop:
>                 os.kill(child.pid, signal.SIGTERM)
>                 log("killed child %i." % child.pid)
>                 break
> 
> class DbLogger(threading.Thread):
>     def __init__(self, queue, *args, **kwargs):
>         self.stop = 0
>         self.queue = queue
>         threading.Thread.__init__(self, *args, **kwargs)
> 
>     def run(self):
>         con = PgSQL.connect()
>         cursor = con.cursor()
>         while 1:
>             if self.stop:
>                 con.close()
>                 break
> 
>             item = self.queue.get()
>             cursor.execute("INSERT INTO LOG(ADDRESS, UP) VALUES (%s, %s)",
>                 (item[0], PgSQL.PgBoolean(item[1])))
>             con.commit()
>             log("committed.")
> 
> def main():
>     pinglist = ["127.0.0.1", "192.168.0.1", "192.168.2.1", "192.168.2.10", "192.168.2.11"]
>     threads = []
>     queue = Queue.Queue()
>     for adr in pinglist:
>         threads.append(Pinger(queue, adr))
> 
>     threads.append(DbLogger(queue)) 
> 
>     for thread in threads:
>         thread.start()
> 
>     try:
>         while 1:
>             time.sleep(1)
>             log("in main loop.")
>     except KeyboardInterrupt:
>         pass
> 
>     for thread in threads:
>         thread.stop = 1
> 
>     for thread in threads:
>         thread.join(2.0)
> 
>     # Ok, I've had enough of you stupid threads.
>     os._exit(0)
> 
> if __name__ == "__main__":
>     main()
> #v-
> 
> If you try this out and are annoyed by the remaining 'ping' processes, here's a
> quick *cough* solution ;-)
> 
> #v+
> import os, signal, commands
> 
> s = commands.getoutput("ps aux|grep ping|grep -v grep")
> for line in s.split("\n"):
>     pid = int(line.split()[1])
>     os.kill(pid, signal.SIGKILL)
> #v-
> 
> Gerhard

Thanks to everyone for the code and suggestions,

Gerhard, I'm trying out your code, as mentioned in the inital post -
I'm fairly new to python, so please bear with me :)

Also, this application has to be run from a windows server, and i was
hoping to execute the script as cgi.

if your still interested, I've been going over the code and have
stripped out the db logging in efforts of getting the multi-threading
working. I'll modify the DbLogger() class to insert into msSQL after I
get the forementioned working...

Here's the stripped down version:
=======================================
import threading
import os, popen2, select, signal
import Queue
import time

HOST_UP = 1
HOST_DOWN = 0

PING_INTERVAL = 5

def log(s):
    print s

class Pinger(threading.Thread):
    def __init__(self, queue, address, *args, **kwargs):
        self.address = address
        self.queue = queue
        threading.Thread.__init__(self, *args, **kwargs)
        self.stop = 0

    def run(self):
        child = popen2.Popen3("ping -i %i %s 2>&1" % (PING_INTERVAL,
self.address))
        log("started child %i" % child.pid)
        while 1:
            ready_fds = select.select([child.fromchild], [], [])

            line = child.fromchild.readline()
            if line.find("Host is down") >= 0:
                log("host %s is down" % self.address)
                self.queue.put((self.address, HOST_DOWN))
            else:
                log("host %s is up" % self.address)
                self.queue.put((self.address, HOST_UP))
            
            if self.stop:
                os.kill(child.pid, signal.SIGTERM)
                log("killed child %i." % child.pid)
                break
				
def main():
    pinglist = ["127.0.0.1"]
    threads = []
    queue = Queue.Queue()
    
    for adr in pinglist:
        threads.append(Pinger(queue, adr))        

    for thread in threads:
        thread.start()

    try:
        while 1:
            time.sleep(1)
            log("in main loop.")
    except KeyboardInterrupt:
        pass

    for thread in threads:
        thread.stop = 1

    for thread in threads:
        thread.join(2.0)

    # Ok, I've had enough of you stupid threads.
    os._exit(0)

if __name__ == "__main__":
    main()
====================================
when I run the script, I get the following error:

Exception in thread Thread-1:
Traceback (most recent call last):
  File "I:\Python22\lib\threading.py", line 408, in __bootstrap
    self.run()
  File "I:\Python22\multi_ping.py", line 22, in run
    child = popen2.Popen3("ping -i %i %s 2>&1" % (PING_INTERVAL,
self.address))
AttributeError: 'module' object has no attribute 'Popen3'

Then the script continues to loop printing out "in main loop". I'm
asssuming that the script is waiting for a response from the Pinger()
class, and continues to loop because Pinger() never finishes
executing?

any ideas?

thanks in advance, .d.hos




More information about the Python-list mailing list