Question

I have a list of IP's (Generated from a traceroute in Python Scapy) which I need to send 3 ping's to measure the average time to each hop. My first methord was building a ICMP request using sockets and measuring the time for response. But it is inaccurate and slow when pinging multiple hosts. I did try and use normal Linux ping, but my for i loop was being blocked while waiting for the response, obviously I want all the ping requests to be send out at the same time.

So I'm looking for a way to use fping in Linux which I give a list of IP's and then let that do the work of building packets. But I'm not sure how to pass a list of arguments to a shell command or get the data back into an array for further processing after it has completed.

Any pointers appreciated!

Was it helpful?

Solution

I don't know much about fping, but something like this...

import subprocess

CMD = ['fping', 'param1', 'param2']

result = subprocess.check_output(CMD)

...will run fping param1 param2, and put the output as a string into the result variable, once the fping process has terminated.

You can split the output into lines with result.splitlines().

Here's quick one-liner example using ping to grab three ping times to localhost...

>>> [line.rpartition('=')[-1] for line in subprocess.check_output(['ping', '-c', '3', 'localhost']).splitlines()[1:-4]]
['0.028 ms', '0.023 ms', '0.025 ms']

OTHER TIPS

The following function parses fping's output and returns a dictionary containing the availability for every host:

import subprocess
from typing import List, Dict

def ping(hosts: List[str], timeout: int = 500) -> Dict[str, bool]:
    command = ["fping", "-t", str(timeout)] + hosts
    proc    = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    parse   = lambda stream: [
        line.split(" ")
        for line
        in stream.read().decode("UTF-8").split("\n")
        if len(line) != 0
    ]
    lines = parse(proc.stdout) + parse(proc.stderr)
    return {p[0]: p[-1] == "alive" for p in lines if p[1] == 'is'}

print(ping(["google.com", "asdfasdfasdf1234.com", "stackoverflow.com"]))
# {'google.com': True, 'stackoverflow.com': True, 'asdfasdfasdf1234.com:': False}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top