Netzwerkscann via Ping

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
dannyboy385
User
Beiträge: 39
Registriert: Freitag 27. November 2015, 21:24

Hallo Community. Hier ein kleines Programm welches der Reihe nach IP Adressen anpingt und ihre erreichbarkeit in einer Datei festhält

Code: Alles auswählen

#! /usr/bin/env python3
import os
def ping(ip):#Pingbefehl an System übergeben
    NED = bool(os.system ("ping -c 1 -w 1 "+ ip))
    return (NED)


def writetofile(data):#Datei öffnen oder wenn nicht vorhande erstellen
    file = open ("pingtestlog.log" , "a")#und data in die Datei schreiben
    file.write (str(data)+ "\n")
    file.close()
    return()
    
def testloop(ip,start,end):
    ipanfang = ip[0:12]#ersten stellen einer IP adresse ermitteln
    ipanfang = ipanfang.replace( "0", "" )#nullen wegstreichen
    liste = [i for i in range (start , end+1)]
    #print (liste)
    for index in liste:
        ip = ipanfang+str(index)#IP aus ipanfang und einem wert auf liste zusammensetzen
        print (ip + "     Wird getestet")
        response = ping(ip)
        if response != True:#Ergebniss auswerten
            data = ip + "  : reachable"
            print (data)
            writetofile(data)
        else :
            data = ip + "  : not reachable"
            print (data)
            writetofile(data)

while(True):#Mainloop
    start=int(1)
    ip = str(input("Erste IP angeben (Es wird bis x.x.x.254 gescand) :  "))
    end = int(input("Bis zu welcher IP soll gescannt werden?:   "))
    testloop(ip,start,end)
Hier habe ich nun das hässliche Problem in Zeile 4 und 5 welches ich gerne umgehen würde. Leider kommt mir hierzu keinerlei Idee in den Kopf dar die Funktion einen Wert 0 oder 255 zurückgiebt wenn man ihn per print ausgiebt, type(NED) aber NoneType ausgiebt was für mich irgendwie keinen SInn ergibt.

2Tens funktioniert das ganze soweit ja ganz gut außer es kommt eine null in einer IP vor.
In Zeile 16 ersetze ich alle 0 in dem string durch "nichts". Nun ist es natürlich möglich das eine gewollte null in der IP wie z.B. 192.168.107.xxx vorkommt. Diese werden ja dann auch gestrichen und es hat nichts mehr mit dem ursprünglich gemeinten netzwerk zu tun.....
Wie könnte ich dieses Problem lösen?

Mir ist klar das einige Codezeilen in einer zusammen gefasst werden könnten. Aber dar ich zum Test immer wieder print ausgaben einfüge um best werte zu prüfen ist dies mommentan noch nicht sinnvoll.

mfg danny385
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Dass NED None, 0 oder 255 ist, ergibt für mich auch keinen Sinn, weil Du es ja explizit nach bool konvertierst. Ein print ergibt also entweder True oder False. Wenn Du nicht willst, dass Nullen verschwinden, dann mach es einfach nicht. Den Sinn der Zeile versteh ich sowieso nicht. Es gibt übrigens das Modul ipaddress, womit Du das ganze Stringherumgemurkse auch sparen kannst. Statt os.system solltest Du auch subprocess.check benutzen. Die Kommentare kleben alle so am Ende von Zeilen, dass man sie kaum findet, und sind meist auch ziemlich aussagenlos, weil sie nur beschreiben, was sowieso eine Zeile davor oder dahinter passiert. Kommentare sollten einen Mehrwert bieten. Warum liefert writetofile ein leeres Tuple zurück?

Code: Alles auswählen

import subprocess
import ipaddress

def ping(ip):
    try:
        subprocess.check_call(["ping", "-c", "1", "-w", "1", str(ip)])
        return True
    except subprocess.CalledProcessError:
        return False
 
def writetofile(data):
    with open("pingtestlog.log" , "a") as f:
        f.write(data + "\n")
   
def testloop(start_ip, end_ip):
    ip = ipaddress.ip_address(start_ip)
    end_ip = ipaddress.ip_address(end_ip)
    while ip <= end_ip:
        print("{}     Wird getestet".format(ip))
        response = ping(ip)
        if response:
            data = "{}  : reachable"
        else:
            data = "{}  : not reachable"
        data = data.format(ip)
        print(data)
        writetofile(data)
        ip += 1

def main():
    while True:
        start_ip = input("Erste IP angeben (x.x.x.x) :  "))
        end_ip = input("Letzte IP angeben (x.x.x.x) :  "))
        testloop(start_ip, end_ip)
        
if __name__ == '__main__':
    main()
BlackJack

Mit dem Modul könnte man auch ein Netzwerk angeben statt zwei IP-Adressen:

Code: Alles auswählen

import subprocess
from ipaddress import ip_network

 
def ping(ip):
    try:
        subprocess.check_call(['ping', '-c', '1', '-w', '1', str(ip)])
        return True
    except subprocess.CalledProcessError:
        return False


def append_to_file(filename, data):
    with open(filename, 'a') as out_file:
        out_file.write(data + '\n')


def ping_hosts(network):
    for ip in network.hosts():
        print('{}     Wird getestet'.format(ip))
        data = '{0}  : {1}'.format(
            ip, 'reachable' if ping(ip) else 'not reachable'
        )
        print(data)
        append_to_file('pingtestlog.log', data)
 

def main():
    while True:
        network = ip_network(input('Netzwerk angeben (x.x.x.x/maske): '))
        ping_hosts(network)


if __name__ == '__main__':
    main()
dannyboy385
User
Beiträge: 39
Registriert: Freitag 27. November 2015, 21:24

Nur mit der expliziten Konvertierung nach bool, ließ sich das Ergebnis überhaupt weiterverarbeiten. Diese konvertierung auch das
If!= True resultiert leider aus "ausprobieren bis es funktioniert "
Desweiteren komm ich nicht dahinter wie ein nonetype einen wert haben kann....
Der rückgabewert von writetofile ist meines Erachtens uninteressant weswegen keine returnanweisung am ende steht.
Es sollen eventuell eingegebene führende nullen welche ja am sagen wir wert der ipadrese nichts ändern aber von ping sehr wohlinterpretiert werden weggestrichen werden.
Z.b. google
8.8.8.8 Ist erreichbar
8.8.8.08 aber nicht.
Es soll nur eine fehlerquelle ausgeschlossen werden.
Ipadress mir nicht bekannt
dannyboy385
User
Beiträge: 39
Registriert: Freitag 27. November 2015, 21:24

Was mir soeben auch noich aufgefallen ist, ist das die Lösung mit meiner Stringmurserei wenn man sie so nennen will Laufzeittechnisch um einiges flotter läuft als die subprocessvariante. Wobei ich mich frage warum das so ist dar mein Quellcode um einiges aufwendiger ist als deine Lösung.
Auch sieht "ipadress" sehr interessant aus. Allein diese möglichkeit der simplen addition (beschrieben unter 21.28.2.3.2. Arithmetic operators) erspart mir in meinem code bereits 3 Zeilen Code.
@Sirius3
Der Laufzeitunterschied wirkt sich natürlich nur auf einen längeren Verlauf des Programms aus
Zuletzt geändert von dannyboy385 am Donnerstag 31. Dezember 2015, 17:37, insgesamt 2-mal geändert.
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

@dannyboy385: ich bezweifle mal, dass es einen signifikanten Laufzeitunterschied geben dürfte, da wohl annähernd 99.9% der Zeit ping mit Netzwerkverbindungen aufbauen verbraucht.
BlackJack

@dannyboy375: Der Typ `NoneType` hat genau einen Wert, und zwar `None`.

Die explizite Konvertierung nach `bool` ist nur nötig wenn man den Rückgabewert explizit mit einem literalen Wahrheitswert vergleicht. Wenn man Rückgabewert schon vor der Rückgabe noch mal verändert, dann sollte man ihn mindestens negieren, denn sonst schaut die API und damit der verwendende Quelltext unlogisch aus.

Wenn Du führende Nullen bei den einzelnen Komponenten beseitigen willst, dann musst Du genau das machen: Die Zeichenkette in die Komponenten zerlegen, bei den einzelnen Komponenten die führenden 0en entfernen, und dann wieder zusammensetzen. Wenn man die IP sowieso zerlegt kann man auch gleich den Wertebereich der Komponenten prüfen, und dann hat man im Grunde einen eigenen Datentyp und sollte den auch implementieren, oder auf das `ipaddress`-Modul zurückgreifen wo das schon jemand getan hat.

Geschwindigkeitsmässig kann man die beiden Programme IMHO schon deswegen nicht vergleichen weil Deins nicht robust funktioniert. Die Definition von `ipanfang` ist schon mal sehr fragwürdig. Je nach dem welche konkreten Werte die Komponenten haben, ist die letzte Komponente ganz, teilweise, oder auch gar nicht enthalten. Beispiel:

Code: Alles auswählen

In [3]: '10.0.0.1'[:12]
Out[3]: '10.0.0.1'
Da würde Dein `testloop()` dann so falsche Adressen wie '10.0.0.1128' anpingen, was natürlich sehr schnell geht, aber schnell ist eben nicht so wichtig wie *richtig*. ;-)
Antworten