nidavellir
Goto Top

Log über Verfügbarkeit einer Datei auf einem Web- und SFTP-Server

Hallo zusammen,

eins vorweg: ich habe minimale Kenntnisse in Skripten und werde mich da auch mehr mit beschäftigen müssen. face-wink
Ich bitte euch um Hilfe bei folgendem Problem.

Ich muss die Erreichbarkeit eines Servers prüfen und loggen. Hintergrund: angeblich ist der Server häufig nicht erreichbar und die Dateien können nicht abgerufen werden.
Es greifen zwei verschiedene Anwendungen auf den Server zu:
1) es wird eine HTML-Datei, welche über einen Webservice (ich glaube Glassfish) bereitgestellt wird, abgerufen
2) eine PDF wird per SFTP nach lokal kopiert

Um das ganze nachzustellen, hat mir ein Kollege eine Textdatei auf dem Server bereit gestellt, welche ich per URL und SFTP erreichen kann.

Ich habe mit dem Punkt 1 begonnen und lade die txt mittels
Invoke-WebRequest -Uri "https://URL/mp_s_testfile.txt" -OutFile "C:\temp\test.txt"  
herunter. Tritt kein Fehler auf, ist der Webservice verfügbar.
Versuche ich eine nicht vorhandene Datei abzurufen, erhalte ich Fehler 1, versuche ich das mit einem Tippfehler in der URL um einen nicht verfügbaren Server zu simulieren, erhalte ich Fehler 2.

Fehler 1:
Invoke-WebRequest : Oops, something went wrong.
In Zeile:1 Zeichen:1
+ Invoke-WebRequest -Uri "https://URL ...  
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

Fehler 2:
Invoke-WebRequest : Die Verbindung mit dem Remoteserver kann nicht hergestellt werden.
In Zeile:1 Zeichen:1
+ Invoke-WebRequest -Uri "https://URL-mitFehler ...  
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

Diese 3 Möglichkeiten möchte ich dann in ein Log schreiben. Weiß aber nicht wie ich es korrekt mache. Ich habe mit Try/Catch gespielt und konnte zumindest bei Fehlern einen Eintrag erzeugen. Da hatte ich das Problem das die erfolgreichen Zugriffe nicht geschrieben werden können, da ich vermutlich mit Sicherheit falsch vorgehe.

Ich habe ein tolles Beispiel für das Schreiben einer Log-Datei gefunden [1] und möchte das gern nutzen.
Kann mich jemand dabei unterstützen? Oder zumindest in die richtige Richtung schubsen?


Viele Grüße
Nidavellir


[1] https://germanpowershell.com/logdatei-erstellen/

Content-ID: 612806

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

Ausgedruckt am: 22.11.2024 um 14:11 Uhr

erikro
erikro 14.10.2020 um 18:17:02 Uhr
Goto Top
Moin,


Zitat von @Nidavellir:

Hallo zusammen,

eins vorweg: ich habe minimale Kenntnisse in Skripten und werde mich da auch mehr mit beschäftigen müssen. face-wink
Ich bitte euch um Hilfe bei folgendem Problem.

Ich muss die Erreichbarkeit eines Servers prüfen und loggen. Hintergrund: angeblich ist der Server häufig nicht erreichbar und die Dateien können nicht abgerufen werden.
Es greifen zwei verschiedene Anwendungen auf den Server zu:
1) es wird eine HTML-Datei, welche über einen Webservice (ich glaube Glassfish) bereitgestellt wird, abgerufen
2) eine PDF wird per SFTP nach lokal kopiert

Hast Du denn schon mal in die Logs des Servers geschaut, was da so steht? Und was steht in den Logs der betroffenen Clients? Was ist der Grund für die Nichterreichbarkeit. Wieso "angeblich"? Meiner Erfahrung nach denken User sich sowas in der Regel nicht aus.

Oder ist das nicht Dein Server? Hast Du dann schon die Kollegen informiert, die den Server betreiben? Meiner Erfahrung nach sind die allermeisten Kollegen, wenn man ihnen anständige Fehlerbeschreibungen mit Originalfehlermeldungen und Logeinträgen zur Verfügung stellt, gerne bereit, das Problem zu lösen.

So, nun die Antwort auf Deine Frage face-wink :
https://www.netz-weise-it.training/weisheiten/powershell-ausgabestroeme- ...

Liebe Grüße

Erik
Nidavellir
Nidavellir 14.10.2020 um 22:16:47 Uhr
Goto Top
Hallo Erik,

die Clients, welche Daten von dem Server laden, befinden sich bei einem Kunden im internen Netz. Der Server liegt bei einem Hoster und wird von uns gezahlt und betreut. Ist eine wichtige Information, habe ich aber scheinbar bei meiner Problemschilderung vergessen. Sorry dafür. face-smile

Der Kunde ist nicht einfach und fordert einen Vergleich "Erreichbarkeit aus dem internen Netz" und "Erreichbarkeit von extern", z. B. aus unserem Netz. Also wenn der Server von intern nicht erreichbar war, wie sah es von extern aus? Mehr ins Detail kann ich leider nicht gehen, ist aber auch für die Frage nicht weiter relevant.

Zu deinem Link:
So richtig komme ich damit nicht weiter. Muss ich mir morgen nochmal in Ruhe durchlesen.

Ich habe folgenden Weg grob im Kopf: der Download wird mittels "Invoke-WebRequest ..." versucht. Gibt es keinen Fehler wird eine entsprechende Meldung ins Log geschrieben. Falls es einen Fehler gibt, muss eine andere Meldung geschrieben werden. In einer Batch habe ich das vor Ewigkeiten über Errorlevel abgefragt. So etwas scheint es hier nicht zu geben?
Nidavellir
Nidavellir 15.10.2020 um 10:17:50 Uhr
Goto Top
Ich habe jetzt mit einer einfacheren Vorlage für die Log-Erstellung weiter gemacht [1], empfinde ich als übersichtlicher.

Dort habe ich mittels if/else die Logik vorbereitet, muss aber noch auf Basis einer eventuellen Fehlermeldung die Prüfung für das if bauen.
Also das Ergebnis des versuchten Abrufs auf die zwei verschiedenen Fehler prüfen. Da komme ich aktuell nicht weiter...

So sieht es im Moment aus:

$path = "C:\temp"  
$date = get-date -format "yyyy-MM-dd"  
$file = ("Log_" + $date + ".log")  
$logfile = $path + "\" + $file  

function Write-Log([string]$logtext, [int]$level=0)
{
	$logdate = get-date -format "yyyy-MM-dd HH:mm:ss"  
	if($level -eq 0)
	{
		$logtext = "[INFO] " + $logtext  
		$text = "["+$logdate+"] - " + $logtext  
		Write-Host $text
	}
	if($level -eq 1)
	{
		$logtext = "[WARNING] " + $logtext  
		$text = "["+$logdate+"] - " + $logtext  
		Write-Host $text -ForegroundColor Yellow
	}
	if($level -eq 2)
	{
		$logtext = "[ERROR] " + $logtext  
		$text = "["+$logdate+"] - " + $logtext  
		Write-Host $text -ForegroundColor Red
	}
	$text >> $logfile
}



if (Prüfung auf "Invoke-WebRequest : Die Verbindung mit dem Remoteserver kann nicht hergestellt werden.") {  
   Write-Log "Server nicht erreichbar" 2  
}
elseif (Prüfung auf "Invoke-WebRequest : Oops, something went wrong.") {  
   Write-Log "Datei nicht vorhanden" 1  
}
else {
   Write-Log "alles iO" 0  
}



[1] https://www.antary.de/2016/11/07/einfaches-logging-fuer-powershell-skrip ...
Nidavellir
Nidavellir 15.10.2020 aktualisiert um 13:57:12 Uhr
Goto Top
Ich denke mir fehlt "nur" noch ein Baustein. Wie bekomme ich den Fehler, welcher bei "Invoke-WebRequest" auftreten kann, korrekt in die Variable $output? Diese wollte ich dann auf die möglichen Meldungen prüfen.

$output = Invoke-WebRequest -Uri $url -OutFile "C:\temp\test.txt"  

#Prüfung auf "Invoke-WebRequest : Die Verbindung mit dem Remoteserver kann nicht hergestellt werden." 
if ($output -like "*Invoke-WebRequest : Die Verbindung mit dem Remoteserver kann nicht hergestellt werden.*" ) {  
   Write-Log "Server nicht erreichbar" 2  
}

Ich vermute der Link von erikro sollte mir an eben dieser Stelle helfen? Also das ich die Ausgabe mittels Write-Verbose für die Variable oder eine Pipe nutzbar mache?
Falls dem so ist: mit welchem Aufbau?

Ich habe es mit folgendem Aufbau versucht, da erhalte ich aber folgenden Fehler.
$output = Write-Verbose (Invoke-WebRequest -Uri $url -OutFile "C:\temp\test.txt") -verbose 2>&1  
Write-Verbose : Das Argument kann nicht an den Parameter "Message" gebunden werden, da es NULL ist.  

Wie bekomme ich also die Fehlermeldung für den -like Operator nutzbar?


EDIT:
Ich habe es mit der Variable $Error versucht, da dort ohnehin die Fehlermeldung landet. Um alte Fehler zu löschen, leere ich die Variable vor der Ausführung.
$error.clear()

$url = "https://URL/mp_s_testfile.txt"  
Invoke-WebRequest -Uri $url -OutFile "C:\temp\test.txt"  

#Prüfung auf "Invoke-WebRequest : Die Verbindung mit dem Remoteserver kann nicht hergestellt werden." 
if ($error -like "*Invoke-WebRequest : Die Verbindung mit dem Remoteserver kann nicht hergestellt werden.*" ) {  
   Write-Log "Server nicht erreichbar" 2  
}

Ist der Inhalt kein auswertbarer Text?


Vollständiges Skript:

$path = "C:\temp"  
$date = get-date -format "yyyy-MM-dd"  
$file = ("Log_" + $date + ".log")  
$logfile = $path + "\" + $file  

function Write-Log([string]$logtext, [int]$level=0)
{
	$logdate = get-date -format "yyyy-MM-dd HH:mm:ss"  
	if($level -eq 0)
	{
		$logtext = "[INFO] " + $logtext  
		$text = "["+$logdate+"] - " + $logtext  
		Write-Host $text
	}
	if($level -eq 1)
	{
		$logtext = "[WARNING] " + $logtext  
		$text = "["+$logdate+"] - " + $logtext  
		Write-Host $text -ForegroundColor Yellow
	}
	if($level -eq 2)
	{
		$logtext = "[ERROR] " + $logtext  
		$text = "["+$logdate+"] - " + $logtext  
		Write-Host $text -ForegroundColor Red
	}
	$text >> $logfile
}



$url = "https://URL/mp_s_testfile.txt"  
$output = Invoke-WebRequest -Uri $url -OutFile "C:\temp\test.txt"  

#Prüfung auf "Invoke-WebRequest : Die Verbindung mit dem Remoteserver kann nicht hergestellt werden." 
if ($output -like "*Invoke-WebRequest : Die Verbindung mit dem Remoteserver kann nicht hergestellt werden.*" ) {  
   Write-Log "Server nicht erreichbar" 2  
}
#Prüfung auf "Invoke-WebRequest : Oops, something went wrong." 
elseif ($output -like "*Invoke-WebRequest : Oops, something went wrong.*") {  
   Write-Log "Datei nicht vorhanden" 1  
}
else {
   Write-Log "alles iO" 0  
}
#Write-Host $output
Nidavellir
Nidavellir 15.10.2020 um 14:32:00 Uhr
Goto Top
Ich hoffe das wird mir hier nicht übel genommen oder als Spam aufgefasst, aber ich selbst hasse es wenn Fragen/Probleme ewig ohne eine Lösung stehen bleiben, auch wenn der Fragesteller eine Lösung gefunden hat...

Ich habe mich hier [1] zu Fehlerbehandlung eingelesen und die Möglichkeit von "$error.Exception" gefunden. Die dort abgelegte Fehlermeldung kann ich mit dem -like Operator verarbeiten und damit funktioniert mein Skript.

Ich bin aber trotzdem dankbar, falls jemand noch seinen Senf dazugeben möchte! Dennoch schon mal danke das ich hier "laut denken" durfte. face-wink


[1] https://www.gngrninja.com/script-ninja/2016/6/5/powershell-getting-start ...

Vollständiges Skript:

$path = "C:\temp"  
$date = get-date -format "yyyy-MM-dd"  
$file = ("Log_" + $date + ".log")  
$logfile = $path + "\" + $file  

function Write-Log([string]$logtext, [int]$level=0)
{
	$logdate = get-date -format "yyyy-MM-dd HH:mm:ss"  
	if($level -eq 0)
	{
		$logtext = "[INFO] " + $logtext  
		$text = "["+$logdate+"] - " + $logtext  
		Write-Host $text
	}
	if($level -eq 1)
	{
		$logtext = "[WARNING] " + $logtext  
		$text = "["+$logdate+"] - " + $logtext  
		Write-Host $text -ForegroundColor Yellow
	}
	if($level -eq 2)
	{
		$logtext = "[ERROR] " + $logtext  
		$text = "["+$logdate+"] - " + $logtext  
		Write-Host $text -ForegroundColor Red
	}
	$text >> $logfile
}

$error.clear()

$url = "https://URL/mp_s_testfile.txt"  
Invoke-WebRequest -Uri $url -OutFile "C:\temp\test.txt"  


if ($error.Exception -like "*Die Verbindung mit dem Remoteserver kann nicht hergestellt werden.*" ) {  
   Write-Log "Server nicht erreichbar" 2  
}
elseif ($error.Exception -like "*Der Remoteserver hat einen Fehler zurückgegeben: (404) Nicht gefunden.*") {  
   Write-Log "Datei nicht vorhanden" 1  
}
else {
   Write-Log "alles iO" 0  
}
erikro
erikro 15.10.2020 aktualisiert um 20:44:54 Uhr
Goto Top
Moin,

Zitat von @Nidavellir:

Ich vermute der Link von erikro sollte mir an eben dieser Stelle helfen?

So ist es. Du kannst Dir das ganze Gedöns mit dem If-else sparen und Dir die Fehlermeldungen direkt ins log schreiben. Pass auf:

PS C:\Users\XXX> get-childitem blah | Out-File test.txt
get-childitem : Der Pfad "C:\Users\XXX\blah" kann nicht gefunden werden, da er nicht vorhanden ist.  
In Zeile:1 Zeichen:1
+ get-childitem blah | Out-File test.txt
+ ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\Users\XXX\blah:String) [Get-ChildItem], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand

PS C:\Users\XXX> cat test.txt

Hier ist test.txt leer.

PS C:\Users\XXX> get-childitem blah 4&>1 | Out-File test.txt
PS C:\Users\XXX> cat test.txt
get-childitem : Der Pfad "C:\Users\XXX\blah" kann nicht gefunden werden, da er nicht vorhanden ist.  
In Zeile:1 Zeichen:1
+ get-childitem blah 2>&1 | Out-File test.txt
+ ~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\Users\XXX\blah:String) [Get-ChildItem], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand

Und hier steht die komplette Fehlermeldung in test.txt.

Warum das so ist, steht in dem Link. Hier nochmal genauer von MS direkt:
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell. ...

Liebe Grüße

Erik
Nidavellir
Nidavellir 15.10.2020 um 20:58:05 Uhr
Goto Top
Danke für deine Erklärung!
Für die Übersichtlichkeit wollte ich nicht die ganze Meldung, sondern nur eine Kurzfassung ins Log schreiben.

Auf jeden Fall hab ich durch die Bastelei ein paar Sachen gelernt. face-smile

Danke & Viele Grüße
Nidavellir
erikro
erikro 15.10.2020 um 21:25:55 Uhr
Goto Top
Zitat von @Nidavellir:

Danke für deine Erklärung!

Gerne.

Für die Übersichtlichkeit wollte ich nicht die ganze Meldung, sondern nur eine Kurzfassung ins Log schreiben.

Der Kunde wäre aber beeindruckt. face-wink Und wenn man so schwachsinnige Wünsche des Kunden erfüllen muss, dann muss man ihm auch geben, was er will. Dinge, die er nicht wirklich versteht. face-wink Vor allem hat aber die Methode den Vorteil, dass Du alle Fehlermeldungen bekommst und nicht nur die, die Du erwartest. face-wink

Trotzdem halte ich das Ansinnen weiter für zweifelhaft. Es sagt nichts über die Erreichbarkeit der Site aus, wenn Du es nur von einem Punkt aus misst. Dafür gibt es Dienstleister wie den hier z. B. (erster Treffer bei Tante Googel, keine Empfehlung):
https://www.uptrends.de/tools/uptime

Sinn macht das Messen einer externen Erreichbarkeit nämlich nur dann, wenn man das von allen möglichen Punkten aus unter verschiedenen Bandbreitenbedingungen testet. Wenn ich hier eine in Deutschland gehostete Site messe, sagt das über die Erreichbarkeit in Peru nichts aus. face-wink

Deshalb würde ich dem Kunden raten, dass er einfach mal ein paar Euro zahlt und so einen Dienst beauftragt. Alles andere ist sinnlos. Außerdem hat der Kunde ja Zweifel an Deiner Dienstleistung. Allein schon deshalb würde ich da auf einen externen Dienstleister bestehen. Wenn der Kunde partout darauf nicht eingeht, würde ich den je nach Situation vielleicht eine Weile selbst bezahlen, um einfach neutrale Zahlen zu haben, falls es darauf ankommt.

Auf jeden Fall hab ich durch die Bastelei ein paar Sachen gelernt. face-smile

Das ist immer gut. Dann noch ein kleiner Hinweis: Du hattest weiter ober erwähnt, dass Du es mit einem try-catch-Konstrukt versucht hast. Das ist eigentlich eine schicke Sache, wenn es um Fehlerbehandlung geht. Man muss dazu nur ein wissen. Du musst an den Befehl, dessen Erfolg Du testen willst, ein
-ErrorAction Continue 
anhängen, sonst funktioniert das nicht richtig. Kommt es nämlich zu einem abbrechenden Fehler, dann wird ohne den Zusatz der catch-Zweig nie ausgeführt, weil ja vorher schon abgebrochen wurde.

Liebe Grüße

Erik
Nidavellir
Nidavellir 19.10.2020 um 13:58:02 Uhr
Goto Top
Zitat von @erikro:
Vor allem hat aber die Methode den Vorteil, dass Du alle Fehlermeldungen bekommst und nicht nur die, die Du erwartest. face-wink
Das ist ein guter Einwand! Mal sehen, ich könnte für auftretende Fehler noch ein zweites Log mit den ausführlichen Meldungen erzeugen lassen.

Trotzdem halte ich das Ansinnen weiter für zweifelhaft. Es sagt nichts über die Erreichbarkeit der Site aus, wenn Du es nur von einem Punkt aus misst. Dafür gibt es Dienstleister wie den hier z. B. (erster Treffer bei Tante Googel, keine Empfehlung):
Die gleiche Prüfung läuft noch von einem anderen Ort aus. Tritt beim Kunde ein Fehler auf, wird das mit dem Log vom zweiten Standort und dem Monitoring vom Server verglichen. Ich bin mir bewusst das das alles nichts ganzes und halbes ist, aber so soll es nun mal sein.

Danke für deine Beteiligung!