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
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
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 607290
Url: https://administrator.de/contentid/607290
Ausgedruckt am: 08.11.2024 um 11:11 Uhr
27 Kommentare
Neuester Kommentar
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:
Gruß
Doskias
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
Moin.
<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)."
}
}
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 . Das lässt sich mindestens um dem Faktor 10000 beschleunigen , 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)."
}
}
- get results of jobs
- cleanup
$_.Powershell.EndInvoke($_.handle)
$_.Powershell.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
Grüße Uwe
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
Unterstützung bei Batch Pinglog Entwicklung
Da ziehe ich wie immer mein vorbereitetes Erklärbär-Schnippselchen
Liegt das Script im selben Verzeichnis in dem man sich gerade befindet, kann man es auch so abkürzen:
Der einfachste Aufruf sieht hier so aus:
Wenn man dem Script Parameter übergeben möchte:
Wenn man "benannte" Parameter übergeben möchte (die einfachen Hochkommas um den Scriptpfad werden benötigt wenn er Leerzeichen beinhaltet):
Man kann auch mehrere Scripte hintereinander ausführen lassen:
Weitere Parameter zeigt einem ein
Anleitung: 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"
Starten 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"
.\script.ps1
Starten 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"
powershell.exe -File "C:\Pfad\Script.ps1" "Parameter 1" "Parameter 2"
powershell.exe -command "&'C:\Pfad\Script.ps1' -par1 'Wert1' -par2 'Wert2'"
powershell.exe -command "&'C:\Pfad\Script1.ps1';&'C:\Pfad\Script2.ps1'"
powershell -?
in einer Konsole an.Starten 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"Und für Anfänger die PS Profis werden möchten empfehle ich folgende Lektüre
Powershell Leitfaden für Anfänger
Pflichtlektüre
- Kapitel 1: Erste Schritte mit PowerShell
- Kapitel 2: Das Hilfesystem
- Kapitel 3: Entdecken von Objekten, Eigenschaften und Methoden
- Kapitel 4: Einzeiler und die Pipeline
- Kapitel 5: Formatierung, Aliase, Anbieter, Vergleich
- Kapitel 6: Flusssteuerung
- Kapitel 7: Arbeiten mit WMI
- Kapitel 8: PowerShell-Remoting
- Kapitel 9: Funktionen
- Kapitel 10: Skriptmodule
- Anhang A: Hilfesyntax
Erweiterte Grundlagen
- Alles, was Sie schon immer über Arrays wissen wollten
- Alles, was Sie schon immer über Hashtabellen wissen wollten
- Was Sie schon immer über PSCustomObject wissen wollten
- docs.microsoft.com/de-de/powershell/scripting/learn/deep-dives/everything-about-string-substitutions?view=powershell-7
- Alles, was Sie schon immer über die IF-Anweisung wissen wollten
- Alles, was Sie schon immer über die switch-Anweisung wissen wollten
- Alles, was Sie schon immer über Ausnahmen wissen wollten
- Alles, was Sie schon immer über $null wissen wollten
- Alles, was Sie schon immer über ShouldProcess wissen wollten
- Verwenden von Erweiterung mit der TAB-TASTE
Zusätzliche Ressourcen
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.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?
Starte es einfach mal in der Powershell ISE Umgebung und poste einen Screenshot.
Auch dort kein Problem mit aktuellem Management Framework
Was gibt dier ein
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.
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.
Deine PS is way too old ...
https://www.microsoft.com/en-us/download/details.aspx?id=54616
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.00000000000000000000000000000000000000000000000000000000000000000000000000000
2 von 3 complet
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
Hier Live-Test auf einem Server 2012 R2 mit PS 5.1
Habs hier auch mal getestet, läuft ohne Probleme mit PS 5.1, nur zur Info an den TO. Und das raaaasend schnell 255 Hosts innerhalb von nicht mal einer Sekunde...
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%
)
)
Wenn's unbedingt Batch sein muss kannst du es bspw. so machen ...
Das Powershell Skript kannst du natürlich auch vollkommen vereinfachen wenn es nicht auf Zeit ankommt, das hat auch keine besonderen Anforderungen ans Framework.
Jetzt hast du wohl oder übel die Qual der Wahl.
Viel Erfolg
Grüße Uwe
@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
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
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
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)Hallo Uwe , das batch gefällt mir gut, nur fehlt mir in der Ausgabe Datei der Server der nicht ereichbar ist.
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 😜.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.
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