pinge-Netzwerk (PowerShell-Funktion)

Die Idee

Ich habe immer wieder die Anforderung, mit ICMP-Echorequests (ping) die Erreichbarkeit von IP-Adressen zu prüfen. Vielleicht kennt ihr das ja aus eurem eigenen Alltag. Sehr beliebt ist diese Aufgabenstellung bei der Suche nach einer freien IP-Adresse.

Mit der PowerShell gibt es natürlich entsprechende Cmdlets, z.B test-connection. Aber diese haben Nachteile:

  • IP-Adressen werden nacheinander angepingt. Sehr viele Adressen aznzupingen benötigt also viel Zeit.
  • Jeder EchoRequest wartet bis zu 1 Sekunde auf einen EchoReply. Sind also sehr viele IP-Adressen nicht erreichbar, dann geht die Laufzeit ins Ungenießbare.

Es muss also eine Alternative her. Den Einstieg zur Optimierung habe ich in dieser kleinen Anweisung gefunden. Ich spreche die Methode Send der Funktion Ping direkt an. Hier kann ich den Timeout-Wert einstellen:

pinge-Netzwerk (PowerShell-Funktion)

Und das ist gerade für lokale Netzwerke mit kurzen Paketlaufzeiten interessant: Statt bei jeder nicht erreichbaren IP-Adresse 1000 Millisekunden zu warten kann ich so den Timeout auf z.B.. 10 Millisekunden heruntersetzen!

Das habe ich in eine PowerShell-Funktion integriert. Diese erwartet beim Aufruf eine Menge von IP-Adressen. Das stellte mich vor eine weitere Herausforderung: Ich möchte z.B. ein ganzes Netzwerksegment alleine durch die Angabe der NetzID anpingen. So wird aus der Eingabe 192.168.1.0/24 die Menge der IP-Adressen 192.168.1.1 bis 192.168.1.254 – und diese Menge soll meine Funktion natürlich selber berechnen… Es war spät und mir kam nur die Idee mit dem Umweg über die binäre Schreibweise von IP-Adressen:

pinge-Netzwerk (PowerShell-Funktion)

Ich konvertierte also eine IP-Adresse von Decimal nach Binary, erhöhe den Binary-Wert um eins und konvertiere das Ergebnis zurück nach Decimal. Das ist dann die FolgeIP. Den Prozess kann ich zwischen einer StartIP und einer EndIP oder von der ersten bist zur letzten IP eines Subnetzes wiederholen. Danach kenne ich alle IP-Adressen.

Von der Idee zum Code

Das sind meine drei kleinen Helfer-Funktionen:

pinge-Netzwerk (PowerShell-Funktion)
pinge-Netzwerk (PowerShell-Funktion)
pinge-Netzwerk (PowerShell-Funktion)

Diese habe ich in eine finale Funktion eingebaut, die ich bequem aufrufen kann.

Optimierung der Laufzeit durch Parallelisierung

Als kleines Extra wollte ich mich aber nicht mit der linearen Abarbeitung der IP-Adressen zufrieden geben. Daher habe ich meine Funktion pinge-Netzwerk mit einer Parallelisierung aufgewertet. Die zu pingenden IP-Adressen werden bei Bedarf durch PowerShell-Jobs in eigenen Unterprozessen angepingt. Die Menge der IPs wird dabei schön aufgeteilt. Das kann man sich so vorstellen:

pinge-Netzwerk (PowerShell-Funktion)

Im blauen PowerShell-Prozess wird die Funktion gestartet. Dabei sollen 254 IP-Adressen angepingt werden. Die Powershell startet 4 Arbeitsprozesse – dieses sind ChildProcess-Objekte unter der eigentlichen PowerShell. Im ProcMon von Sysinternals kann man das gut sehen:

pinge-Netzwerk (PowerShell-Funktion)

Jeder der Arbeitsprozesse erhält eine Teilmenge der zu pingenden IP-Adressen. Alle Arbeitsprozesse arbeiten parallel. Die PowerShell selber arbeitet als Controller und überwacht den Fortschritt. Sind alle Arbeitsprozesse fertig, dann holt sich die PowerShell deren Ergebnisse und stellt sie als Ausgabe zusammen:

pinge-Netzwerk (PowerShell-Funktion)

Das fertige Script

Das fertige Script habe ich zur besseren Strukturierung in einzelne Regionen unterteilt. Damit kann man relativ einfach durch die Anweisungen navigieren:

pinge-Netzwerk (PowerShell-Funktion)

Im oberen Block sind die drei Hilfsfunktionen integriert. Die Parametervalidierung soll Fehleingaben wie z.B. die IP-Adresse 192.168.1.500 verhindern. In der Region „Bestimmung der IP-Adressen“ wird die Menge der IPs ermittelt. Den eigentlichen Ping habe ich sowohl linear als auch in der Parallel-Variante integriert. Dabei kann die Funktion die Anzahl der Arbeitsprozesse auch selber bestimmen. Abschließend wird die Ausgabe zusammengestellt. Eigentlich recht einfach, oder?

Das hier ist der finale Scriptcode inklusive der Hilfe:

Mögliche Aufrufe

Das sind nun mögliche Aufrufe:

AufrufFunktion
pinge-Netzwerk -Subnetz 192.168.100.0/27 -parallel -AnzahlProzesse 3Die IP-Adressen von 192.168.100.1 bis 192.168.100.30 werden in 3 Arbeitsprozessen gepingt
pinge-Netzwerk -StartIP 192.168.100.1 -EndIP 192.168.100.25 -AnzahlProzesse 6Die IP-Adressen von 192.168.100.1 bis 192.168.100.25 werden in 6 Arbeitsprozessen gepingt.
pinge-Netzwerk -StartIP 192.168.100.1 -EndIP 192.168.100.10Die IP-Adressen von 192.168.100.1 bis 192.168.100.10 werden hintereinander ohne Arbeitsprozesse gepingt.
pinge-Netzwerk -StartIP 192.168.100.1 -EndIP 192.168.100.10 -Filter TimedOutIP-Adressen von 192.168.100.1 bis 192.168.100.10 werden hintereinander ohne Arbeitsprozesse gepingt. Ausgegeben werden nur fehlgeschlagene pings.
pinge-Netzwerk -Subnetz 192.168.100.0/27 -TimeOut 3 -parallel -VerboseDie IP-Adressen von 192.168.100.1 bis 192.168.100.30 werden mit einem maximalen Timeout von 3 Millisekunden gepingt. Die PowerShell ermittelt selbstständig die Anzahl der Arbeitsprozesse. Es werden Zusatzinformationen ausgegeben.

Zusammenfassung

Die Funktion ist fertig. Ich habe sie in mein Standard-Funktionsmodul integriert. So steht sie mir bei jedem PowerShell-Start zur Verfügung. Und hier gibt es noch das zip-Archiv mit dem Script.

Stay tuned!

Kommentar hinterlassen