tommhii
Goto Top

Mehrere Server anpingen positive und negative Ergebnis in Datei schreiben

Hallo ich hab eine Frage ich habe in einer Liste mehrere Server eingetragen die ich per batch anpingen will. Das funktioniert so weit nur will ich nach 2 verschieden Begriffen suchen und das was zu trifft in eine Datei schreiben.

echo off & setlocal enabledelayedexpansion
set aktdatum=%date:~6,4%%date:~3,2%%date:~0,2%
set aktzeit=%time:~0,2%%time:~3,2%%time:~6,2%
for /f %%i in (ip.txt) do (ping -n 1 %%i|find /i "TTL" >>ergebnis%aktdatum%-%aktzeit%.txt)
if errorlevel 1 goto nichtpingbar

hier frage ich nach TTL ab aber ich will noch nach einen zweiten Begriff abfragen und in die Liste eintragen lassen.
der 2. Begriff soll für nicht erreichbare Server sein.

VG Tommhi

Content-ID: 607290

Url: https://administrator.de/contentid/607290

Ausgedruckt am: 26.11.2024 um 14:11 Uhr

Doskias
Doskias 24.09.2020 aktualisiert um 15:23:22 Uhr
Goto Top
Moin

also wenn ich dich, trotz der fehlenden Satzzeichen richtig verstanden habe, dann willst du abhängig vom ping entweder den einen oder den anderen Wert in eine Datei schreiben. Was ich noch nicht ganz verstanden habe ist, was du in die Datei schreiben willst. Ich persönlich würde es via PowerShell lösen und zwar wie folgt:

if(Test-Connection -Count 1 [Server] -Quiet)
{
Befehl wenn wahr
}
else
{
Befehl wenn falsch
}

Gruß
Doskias
colinardo
colinardo 24.09.2020 aktualisiert um 16:34:51 Uhr
Goto Top
Moin.
Ich persönlich würde es via PowerShell lösen und zwar wie folgt:
Test-Connection ist so was von lahm vor allem wenn nichts am Ende reagiert, und dann noch nicht mal parallelisiert face-wink. Das lässt sich mindestens um dem Faktor 10000 beschleunigen face-smile, guckst du...
<code >
<#
Ping mass huge amount of hosts in parallel multithreading
#>

function Parallel-Ping {
[CmdletBinding()]
param(
[parameter(mandatory=$true)][ValidateNotNullOrEmpty()][string[]]$hosts,
[parameter(mandatory=$false)][ValidateNotNullOrEmpty()][int]$timeout = 2000,
[parameter(mandatory=$false)][ValidateNotNullOrEmpty()][ValidateRange(1,255)][int]$ttl = 128,
[parameter(mandatory=$false)][ValidateNotNullOrEmpty()][bool]$DontFragment = $false,
[parameter(mandatory=$false)][ValidateNotNullOrEmpty()][byte[]]$data = ([byte[]]0),
[parameter(mandatory=$false)][ValidateNotNullOrEmpty()][int]$MaxConcurrent = [System.Environment]::ProcessorCount,
[parameter(mandatory=$false)][ValidateNotNullOrEmpty()][switch]$showprogress
)
begin{
$rspool = [runspacefactory]::CreateRunspacePool(1,$MaxConcurrent)
$rspool.ApartmentState = 'STA'
$rspool.Open()
$jobs = New-Object System.Collections.ArrayList
}
process{
foreach ($hostname in $hosts){
$ps = [Powershell]::Create()
$ps.RunspacePool = $rspool
[void]$ps.AddScript({
param($hostname,$timeout,$ttl,$DontFragment,$data)
$result = [ordered]@{Host=$hostname;Address=$null;Status=[System.Net.NetworkInformation.IPStatus]::Unknown;RoundtripTime = -1;TTL=$ttl;DontFragment=$DontFragment;ResponseBuffer='';Time=(get-date)}
$ping = New-Object System.Net.NetworkInformation.Ping
try{
$reply = $ping.Send($hostname,$timeout,$data,(New-Object System.Net.NetworkInformation.PingOptions($ttl,$DontFragment)))
$result.RoundtripTime = $reply.RoundtripTime
$result.Status = $reply.Status
$result.Address = $reply.Address
$result.ResponseBuffer = $reply.Buffer
}catch [System.Net.NetworkInformation.PingException] {
$result.Status = [System.Net.NetworkInformation.IPStatus]::DestinationHostUnreachable
}finally{
$ping.Dispose()
}
[pscustomobject]$result
}).AddParameters(@($hostname,$timeout,$ttl,$DontFragment,$data))
$job = $ps.BeginInvoke()
[void]$jobs.Add(([pscustomobject]@{Handle = $job; Powershell = $ps}))
}
}
end{
write-verbose "Waiting for all jobs to complete."
while(($jobs | ?{!$_.Handle.IsCompleted})){
if ($showprogress.IsPresent){
$completed = ($jobs | ?{$_.Handle.IsCompleted}).Count
Write-Progress -Activity $PSCmdlet.MyInvocation.InvocationName -Status "Pinging a total of $($hosts.Count) hosts." -PercentComplete (($completed / $hosts.Count) * 100) -CurrentOperation "Completed $completed from $($hosts.Count)."
}
}
                  1. get results of jobs
                  $results = $jobs | %{
                  $_.Powershell.EndInvoke($_.handle)
                  $_.Powershell.Dispose()
                  }
                                  1. cleanup
                                  $rspool.Close();$rspool.Dispose()
                                  $results
                                  }
                                  }

                                  $hosts = Get-Content 'E:\ips.txt'
                                  Parallel-Ping -hosts $hosts -timeout 500 -MaxConcurrent 50 -showprogress | ogv

                                  Das Zeigt dir erst mal nur alle Hosts und deren Details in einem Gridview an.
                                  Um das ganze in eine CSV-Datei zu schreiben einfach die letzte Zeile austauschen durch (Ausgabepfad natürlich anpassen)
                                  Parallel-Ping -hosts $hosts -timeout 500 -MaxConcurrent 50 -showprogress | export-csv 'E:\Ausgabe\pings.csv' -Delimiter ";" -NoType -Encoding UTF8  
                                  Dateiname aus der die Hosts geladen werden in vorletzter Zeile anpassen.

                                  screenshot


                                  Grüße Uwe
cs-websystem
cs-websystem 24.09.2020 um 15:34:20 Uhr
Goto Top
GGf hilft dir mein Skript weiter auch wenn ich hierzu noch fragen hier gestellt habe. ich denke für dich könnte es passen

Unterstützung bei Batch Pinglog Entwicklung
Doskias
Doskias 24.09.2020 um 15:53:54 Uhr
Goto Top
Ich sag mal so:

Wir sind die Admins. Ihr Skript wird unserer Sammlung hinzugefügt. Wiederstand ist zwecklos.
tommhii
tommhii 24.09.2020 um 16:06:37 Uhr
Goto Top
Danke erstmal an alle für die schnelle Antwort.
@uwe Dein Powershell script sieht interessant aus, leider hab ich mit Powershell noch nicht gearbeitet , vielleicht kannst Du mir ja mal einen Tip geben wie man das Script unter Powershell anlegt. Ich hätte das jetzt als txt Datei gespeichert und dann als ps1 umbenannt.
ist das so okay
colinardo
colinardo 24.09.2020 aktualisiert um 16:13:59 Uhr
Goto Top
Da ziehe ich wie immer mein vorbereitetes Erklärbär-Schnippselchen

back-to-topAnleitung: Wie starte ich Powershell-Scripte
  • Zuerst speichert man den Code in einer Textdatei mit der Endung .ps1.
  • Wenn man zum ersten mal Powershell-Scripte ausführt, musst man einmalig vorher noch das Ausführen von Scripten im User-Account freischalten. Dazu öffnet man eineadministrative Powershell-Konsole und gibt dort den Befehl Set-ExecutionPolicy RemoteSigned -Force ein. Um diese Policy für alle User auf dem Rechner zu setzen muss man diesen Befehl in einer Powershell-Konsole mit Admin-Rechten starten. Noch ein Hinweis für 64-Bit-Systeme: Hier sollte sowohl für die 32bit und 64Bit Variante der Powershell die Policy in einer Admin-Konsole gesetzt werden: Set-ExecutionPolicy RemoteSigned -Force; start-job { Set-ExecutionPolicy RemoteSigned -Force } -RunAs32
  • Jetzt kann das Powershell-Script wie weiter unten erläutert in einer Powershell-Konsole oder aus einer CMD-Fenster heraus ausgeführt werden. Wer lieber mit der Maus arbeitet macht einen Rechtsklick auf die Script-Datei und wählt: Mit Powershell ausführen.
  • Alternativ lässt sich ein Script auch ohne das globale Ändern der ExecutionPolicy ausführen indem man die Policy als Parameter auf der Kommandozeile mitgibt:
powershell.exe -ExecutionPolicy ByPass -File "C:\Pfad\Script.ps1"
back-to-topStarten eines Scriptes in einer Powershell-Konsole
Immer den kompletten Pfad zum Script angeben, und wenn er Leerzeichen beinhaltet in Anführungszeichen einschließen:
"C:\Pfad\script.ps1"
Liegt das Script im selben Verzeichnis in dem man sich gerade befindet, kann man es auch so abkürzen:
.\script.ps1
back-to-topStarten von PS-Scripten aus Batch und Kommandozeilen heraus:
Hier gibt es unterschiedliche Methoden, je nach Anforderungen gibt es hier einige Besonderheiten vor allem bei Leerzeichen in Pfaden zu beachten!
Der einfachste Aufruf sieht hier so aus:
powershell.exe -File "C:\Pfad\Script.ps1"
Wenn man dem Script Parameter übergeben möchte:
powershell.exe -File "C:\Pfad\Script.ps1" "Parameter 1" "Parameter 2"
Wenn man "benannte" Parameter übergeben möchte (die einfachen Hochkommas um den Scriptpfad werden benötigt wenn er Leerzeichen beinhaltet):
powershell.exe -command "&'C:\Pfad\Script.ps1' -par1 'Wert1' -par2 'Wert2'"
Man kann auch mehrere Scripte hintereinander ausführen lassen:
powershell.exe -command "&'C:\Pfad\Script1.ps1';&'C:\Pfad\Script2.ps1'"
Weitere Parameter zeigt einem ein powershell -? in einer Konsole an.
back-to-topStarten von PS-Scripten in der Aufgabenplanung (Taskplaner)
In der jeweiligen Aktion unter "Programm/Script" trägt man powershell.exe ein und unter "Argumente hinzufügen (optional)" trägt man wie oben geschrieben alles was hinter powershell.exe kommt ein - also z.B. -File "C:\Pfad\Script.ps1" "Parameter 1" "Parameter 2"


back-to-topUnd für Anfänger die PS Profis werden möchten empfehle ich folgende Lektüre


back-to-topPowershell Leitfaden für Anfänger

back-to-topPflichtlektüre
back-to-topErweiterte Grundlagen
back-to-topZusätzliche Ressourcen
tommhii
tommhii 24.09.2020 um 16:22:55 Uhr
Goto Top
Danke für die Erklärung super.
Ich hab jetzt Dein Script als ps1 abgelegt wenn ich es starte öffnet sich kurz ein fenster und geht wieder zu. Ich habe in meiner Datei keine Ip Adressen sondern 8stellige Rechner namen ist das ein Problem?
colinardo
colinardo 24.09.2020 aktualisiert um 16:27:38 Uhr
Goto Top
Zitat von @tommhii:
Ich hab jetzt Dein Script als ps1 abgelegt wenn ich es starte öffnet sich kurz ein fenster und geht wieder zu. Ich habe in meiner Datei keine Ip Adressen sondern 8stellige Rechner namen ist das ein Problem?
Nein ist kein Problem du kannst Hostnamen oder IP Adressen benutzen das der Funktion egal. Hast du denn im Skript den Pfad zu deiner Textdatei angepasst, und auch den Pfad zur Ausgabedatei? Hast du die Executionpolicy angepasst oder das Skript mit -ExecutionPolicy ByPass aufgerufen? Deine Powershell ist aktuell? Das Skript erwartet die Namen untereinander stehend.
Starte es einfach mal in der Powershell ISE Umgebung und poste einen Screenshot.
tommhii
tommhii 24.09.2020 um 16:34:35 Uhr
Goto Top
Pfad zur Eingabe Datei habe ich angepasst , Namen stehen untereinander, gestartet mit Powershell ISE, er zeigt mir nicht das gridview an bzw. pop ganz kurz ein Fenster auf und geht wieder zu. Mit Ausgabe Datei meinst du sicher die csv Datei, das habe ich noch nicht angelegt.
colinardo
colinardo 24.09.2020 aktualisiert um 16:43:01 Uhr
Goto Top
Welches OS? Welche PS Version?
Wenn noch auf W7 /2012R2 etc. bitte Management-Framework Update machen.

Geht hier einwandfrei.
tommhii
tommhii 24.09.2020 um 16:39:08 Uhr
Goto Top
win 2012 R2
colinardo
colinardo 24.09.2020 aktualisiert um 16:42:42 Uhr
Goto Top
Auch dort kein Problem mit aktuellem Management Framework

Was gibt dier ein

$psversiontable

in der Konsole aus?

Wen du natürlich die letzte Zeile bereits wie oben geschrieben ausgetauscht hast kommt selbstredend keine Ausgabe denn die Daten werden dann ja ohne Umweg in die Datei geschrieben ohne irgendwelche Ausgabe.
tommhii
tommhii 24.09.2020 um 16:46:40 Uhr
Goto Top
PSVersion 4.0
WSManStackVersion 3.0
SerializationVersion 1.1.0.1
CLRVersion 4.0.30319.42000
BuildVersion 6.3.9600.19170
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0}
PSRemotingProtocolVersion 2.2
die letzte Zeile habe ich nicht geändert er schreibt irgendwas aus wie 2 von Complet und viele 00000
tommhii
tommhii 24.09.2020 um 16:48:23 Uhr
Goto Top
also da steht Ping total auf 3 Host
00000000000000000000000000000000000000000000000000000000000000000000000000000
2 von 3 complet
colinardo
colinardo 24.09.2020 aktualisiert um 16:52:58 Uhr
Goto Top
Deine PS is way too old ...
https://www.microsoft.com/en-us/download/details.aspx?id=54616
also da steht Ping total auf 3 Host
00000000000000000000000000000000000000000000000000000000000000000000000000000
2 von 3 complet
Das ist die Progress-Anzeige, die kannst du mit dem Weglassen des Parameters -showprogress in der letzen Zeile ausblenden.
tommhii
tommhii 24.09.2020 um 16:55:55 Uhr
Goto Top
das heisst so wie bei Dir die Ergebnis anzeige kommt bekomme ich nicht
colinardo
colinardo 24.09.2020 aktualisiert um 17:00:10 Uhr
Goto Top
Zitat von @tommhii:

das heisst so wie bei Dir die Ergebnis anzeige kommt bekomme ich nicht
Entweder Management Framework Update fahren und deine Textdatei überprüfen (Encoding). Geht wie gesagt einwandfrei wenn du das beachtest.

Hier Live-Test auf einem Server 2012 R2 mit PS 5.1

screenshot
145916
145916 24.09.2020 aktualisiert um 17:04:53 Uhr
Goto Top
Habs hier auch mal getestet, läuft ohne Probleme mit PS 5.1, nur zur Info an den TO. Und das raaaasend schnell face-smile 255 Hosts innerhalb von nicht mal einer Sekunde...
tommhii
tommhii 24.09.2020 um 17:04:46 Uhr
Goto Top
ja danke dann muss ich das wohl doch auf dos batch probieren. aber vielleicht kannst Du mir da weiterhelfen.
wie muss ich diese Zeile ändern wenn ich noch nach einen 2. Begriff suchen tu
for /f %%i in (ip.txt) do (ping -n 1 %%i|find /i "TTL" >>ergebnis%aktdatum%-%aktzeit%.txt)
das bräuchte ich noch --> |find /i "UN"
145916
145916 24.09.2020 aktualisiert um 17:30:21 Uhr
Goto Top
das bräuchte ich noch --> |find /i "UN"
Das ist überflüssig da steht ja eh nichts nutzbares drin, einfach eine oder Bedingung dran pappen und fertig:
@echo off
set "file=D:\ip.txt"  
set "logfile=D:\test.log"  

for /f "usebackq delims=" %%a in ("%file%") do (  
	ping -n 1 %%a | findstr TTL >nul 2>&1 && (
		echo %date% %time% : Host '%%a' online. >>%logfile%  
	) || (
		echo %date% %time% : Host '%%a' nicht erreichbar. >>%logfile%  
	)
)
Aber sowat noch mit Batch zu machen ist echt 80zger Jahre, da muss man a gleich den Käfer wieder aus der Scheune holen face-big-smile.
colinardo
colinardo 24.09.2020, aktualisiert am 25.09.2020 um 08:55:49 Uhr
Goto Top
Wenn's unbedingt Batch sein muss kannst du es bspw. so machen ...
@echo off &setlocal enabledelayedexpansion
set "file=%~dp0ip.txt"  
set aktdatum=%date:~6,4%%date:~3,2%%date:~0,2%
set aktzeit=%time:~0,2%%time:~3,2%%time:~6,2%
set "logfile=%~dp0ergebnis%aktdatum%-%aktzeit%.log"  

>"%logfile%" (for /f "usebackq delims=" %%a in ("%file%") do (  
	set "line="  
	for /f "skip=2 delims=" %%b in ('ping -n 1 %%a') do (  
		if not defined line (set "line=1"&&echo %date% %time% ^| HOST: %%a ^| %%b)  
	)
        if not defined line (set "line=1"&&echo %date% %time% ^| HOST: %%a ^| Zielhost nicht erreichbar)  
))

Das Powershell Skript kannst du natürlich auch vollkommen vereinfachen wenn es nicht auf Zeit ankommt, das hat auch keine besonderen Anforderungen ans Framework.
$ping = New-Object System.Net.NetworkInformation.Ping
Get-Content .\ip.txt -PipelineVariable hostname | %{
    try{
        $ping.Send($_)
    }catch{
        [pscustomobject]@{Status=$_.Exception.Message;Address=$hostname;RoundTripTime=0}
    }
} | select Address,Status,RoundTripTime | ogv

Jetzt hast du wohl oder übel die Qual der Wahl.

Viel Erfolg
Grüße Uwe
lcer00
lcer00 24.09.2020 um 21:07:07 Uhr
Goto Top
Hallo,

falls der TO eigentlich nur ein paar hosts überwachen will, sei neben Powershell darauf hingewiesen, dass man beispielsweise mit PRTG 100 freie Sensoren nutzen kann, die alle fein säuberlich notieren.

Grüße

lcer
tommhii
tommhii 25.09.2020 aktualisiert um 07:21:27 Uhr
Goto Top
Hallo Uwe , das batch gefällt mir gut, nur fehlt mir in der Ausgabe Datei der Server der nicht ereichbar ist.
Powershell werd ich dann auch nochmal testen.

VG
Tommhi
colinardo
colinardo 25.09.2020 aktualisiert um 07:41:56 Uhr
Goto Top
Zitat von @tommhii:

Hallo Uwe , das batch gefällt mir gut, nur fehlt mir in der Ausgabe Datei der Server der nicht ereichbar ist.
Doch, der ist mit drin. (In Zeile 10 wird dieser für jeden Host hinter dem String "HOST:" in das Logfile geschrieben)
tommhii
tommhii 25.09.2020 um 08:24:20 Uhr
Goto Top
Hallo Uwe
ich habe in meiner Liste 3 Server davon sind 2 oben. in der Liste zeigt er mir auch nur die 2 an, den 3. der runtergefahren ist zeigt er nicht an.

hier die Ausgabe
25.09.2020 8:14:11,83 | HOST: T1122380 | Antwort von 10.XX.XX.64: Bytes=32 Zeit<1ms TTL=126
25.09.2020 8:14:11,83 | HOST: T1198mno | Antwort von 10.XX.XX.20: Bytes=32 Zeit=1ms TTL=128

das Powershell hab ich auch mal probiert aber das Fenster geht kurz auf aber zu kurz kann man das auch in eine Datei schreiben.

VG

Tommhi
colinardo
colinardo 25.09.2020 aktualisiert um 08:47:37 Uhr
Goto Top
Zitat von @tommhii:

Hallo Uwe
ich habe in meiner Liste 3 Server davon sind 2 oben. in der Liste zeigt er mir auch nur die 2 an, den 3. der runtergefahren ist zeigt er nicht an.
Nö, geht auch hier testweise einwandfrei. Bei dir scheint wohl überhaupt nix zu laufen 😜.
das Powershell hab ich auch mal probiert aber das Fenster geht kurz auf aber zu kurz kann man das auch in eine Datei schreiben.
Ja, siehe oben , hänge einfach ein export-csv an die Pipe. Man oh man der Server gehört mal ordentlich aufgesetzt 😉.

$ping = New-Object System.Net.NetworkInformation.Ping
Get-Content .\ip.txt -PipelineVariable hostname | %{
    try{
        $ping.Send($_)
    }catch{
        [pscustomobject]@{Status=$_.Exception.Message;Address=$hostname;RoundTripTime=0}
    }
} | select Address,Status,RoundTripTime | export-csv .\pinglog.csv -NoType -Delimiter ";"  

So bin hier nun raus, schon genug Zeit mit diesen Kinderspielchen verplempert.

Grüße Uwe
tommhii
tommhii 25.09.2020 um 09:06:11 Uhr
Goto Top
also das bei mir nix läuft kann man so nicht sagen face-smile
also die batch eaglefinder weisst mir alle 3 server aus. Das versteh ich jetzt echt nicht das es bei Dir geht hab nochmal alles überprüft kann aber keinen fehler finden. face-sad(

VG
Tommhi