import subprocess import re import json import ipaddress from datetime import datetime from sys import hash_info import pprint def run_traceroute(host): timestamp = datetime.now().timestamp() result = subprocess.run(['traceroute', host], stdout=subprocess.PIPE) return result.stdout.decode(), timestamp def parse_traceroute_output(output, timestamp): lines = output.strip().split('\n') hops = [] ip_regex = r"\((.*?)\)" # ipaddress are in () target = output.strip().split('\n')[0].split()[2] for line in lines[1:]: hop = {} hop_info = line.split() hop_number = int(hop_info[0]) hop_name = None hop_ip = None hop_latency = None latencies = [] #print("##### "+str(hop_info)) count = 0 for part in hop_info[1:]: count += 1 # source node drops or blocks icmp packages # We will give funny to name to hop for not answering and move on. if part == '*': hop_name = 'hop.'+str(count)+'.'+str(target) break # If first colum is either name or ip-address if count == 1: match = re.search(ip_regex, part) if match: hop_ip = part.strip('()') else: hop_name = part # Second colum is ip-address first latency reading if count == 2: if re.search(ip_regex, part): try: _ip = ipaddress.ip_address(part.strip('()')) hop_ip = part.strip('()') except ValueError: pass # Ignore if it's not a valid IP address # Rest of the input colums are either latency floats, 'ms' or # reruns of the hop_name and hop_ip... # We only need the latency floats anymore. else: try: latency = float(part) latencies.append(latency) except ValueError: pass hop_latency = sum(latencies) / len(latencies) if latencies else None hop['timestamp'] = timestamp hop['hop_number'] = hop_number if not hop_name == None: hop['hop_name'] = hop_name hop['hop_ip'] = hop_ip hop['hop_latency'] = hop_latency hops.append(hop) return target, hops if __name__ == '__main__': target='8.8.8.8' traceroute_output, timestamp = run_traceroute(target) target, hops = parse_traceroute_output(traceroute_output, timestamp) print('>> '+target) pprint.pprint(hops)