Multiple Ping Script in Python

multiple ping script keeps pinging the same ips from one list several times

It seems the problem is that you're splitting the list of num+i and forward and not grabbing the index value of num+i.
(Also since num is never incremented in your bottom loop, atm it serves no function)

Let's say I have a list that looks like this:

['1.1.1.1','8.8.8.8','8.8.4.4']

Currently you're splitting it like this over the 3 iterations of spawning threads:

['1.1.1.1','8.8.8.8','8.8.4.4']
['8.8.8.8','8.8.4.4']
['8.8.4.4']

This is simply caused by your : operator in your indexing when spawning the thread here:

for i in range(len(ip_list)):
t = Thread(target=ipPinger, args=(ip_list[num + i:],)) #Colon operator in indexing
t.start()

Since your IpPing function takes a list as an argument and a loop through that list it will then loop through the entire list and ping them all, for each thread.

I would also like you to consider that instead of spawning a thread for each IP to ping (in case a big list may be supplied), that you instead may want to spawn either a fixed amount of threads or a variable amount of threads
specified by the user.

Then have each thread pop values from the same list, or handle accessing that list through locks. Since the pinging here takes long and the access to the object is very short.

Good luck with your coding! :-)

Edit: Wording.

Python ping script

You should print the result immediately after pinging each hostname. Try this:

import os

hostnames = [
'10.40.161.2',
'10.40.161.3',
'10.40.161.4',
'10.40.161.5',
]

for hostname in hostnames:
response = os.system('ping -c 1 ' + hostname)
if response == 0:
print(hostname, 'is up')
else:
print(hostname, 'is down')

Also, you should consider using the subprocess module instead of os.system() as the latter is deprecated.

Pinging servers in Python

This function works in any OS (Unix, Linux, macOS, and Windows)
Python 2 and Python 3

EDITS:

By @radato os.system was replaced by subprocess.call. This avoids shell injection vulnerability in cases where your hostname string might not be validated.

import platform    # For getting the operating system name
import subprocess # For executing a shell command

def ping(host):
"""
Returns True if host (str) responds to a ping request.
Remember that a host may not respond to a ping (ICMP) request even if the host name is valid.
"""

# Option for the number of packets as a function of
param = '-n' if platform.system().lower()=='windows' else '-c'

# Building the command. Ex: "ping -c 1 google.com"
command = ['ping', param, '1', host]

return subprocess.call(command) == 0

Note that, according to @ikrase on Windows this function will still return True if you get a Destination Host Unreachable error.

Explanation

The command is ping in both Windows and Unix-like systems.

The option -n (Windows) or -c (Unix) controls the number of packets which in this example was set to 1.

platform.system() returns the platform name. Ex. 'Darwin' on macOS.

subprocess.call() performs a system call. Ex. subprocess.call(['ls','-l']).

Multithreading. How to ping several IPs simultaneously properly?

You don't need threads to execute multiple processes - Just use subprocess.Popen - it doesn't block like os.system, so you can just run it multiple times and they will all run in parallel.

If b is a list that contains all your ips:

import subprocess

while True:
result = []
for ip in b:
p = subprocess.Popen(['ping', '-n', '1', ip]) # runs ping in background
result.append(p) # store the Popen object for later result retrieval

That will run multiple ping processes in the background! Now you just need to parse the results:

    try_again = []
for ip, p in zip(b, result):
if p.wait() == 0:
print(ip, 'is ok!')
else:
print(ip, 'failed!')
try_again.append(ip)

You can then repeat the ones that failed if you want:

    if not try_again:
break
time.sleep(100)
b = try_again


Related Topics



Leave a reply



Submit