l.jablonski
Goto Top

Zeitstempel von Dateien überprüfen bzw. vergleichen und melden

Hallo Zusammen,

Kurze Vorgeschichte:
Wir haben mehrere Hotfolder, bei denen automatisch Dokumente rausgezogen werden und automatisch archiviert + durchsuchbar gemacht werden. Nun ist schon einige male passiert, dass der Dienst die Dateien nicht mehr verarbeitet hat, obwohl der Dienst noch lief. Deswegen können wir auch keine Dienst Überwachung nutzen.

Nun zu meiner Frage, gibt es die Möglichkeit bzw. hat jemand schon eine Lösung, wie ich meine ganzen Dateien überwachen kann mit dem erstellten Zeitstempel der Dokumente.

Bedeutet ich überwache den erstellten Zeitstempel und vergleiche ihn mit der aktuellen Systemzeit, wenn die Differenz größer als 10 min sein sollte, sende mir eine Nachricht per Mail oder anderen Wegen.

Ich wäre für jede Idee offen, seien es Programme oder Batch Skripte, ich habe bei meiner Internet Recherche kein Erfolg gehabt.

Auch meine verzweifelten selbstversuchen, ein solches Batch zu entwerfen sind leider nicht Erfolg gekrönt.

Ich danke euch für euer Feedback!

Ich hoffe irgendjemand kann mir weiterhelfen

Grüße

Content-Key: 666212

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

Printed on: May 4, 2024 at 19:05 o'clock

Member: em-pie
em-pie Apr 28, 2021 updated at 18:50:05 (UTC)
Goto Top
Moin,

Nimm die Powershell:
Mit Get-ChildItem kannst du dir Ordnerinhalte ermitteln.

Mit einem for each kannst du dir dann das Datum jeder einzelnen Datei ermitteln .LastWriteTime
Dann noch mit der aktuellen Systemzeit (abzüglich 10 Minuten .AddMinutes(-10)) vergleichen.
Wenn ein Delta vorhanden ist, dann tu etwas.

z.B. hier
https://stackoverflow.com/questions/19774097/finding-modified-date-of-a- ...

Allerdings würde hier für JEDE Datei eine Altion ausgeführt werden. Daher würde ich eine Schleife erstellen. Sobald mit dem ersten Treffer wird dann eine Aktion ausgeführt (Mail versenden) und die Schleife beendet.

Bei 300 Dateien muss ich die Info ja nur einmal und nicht 300 mal erhalten face-smile

Gruß
em-pie
Member: mbehrens
mbehrens Apr 28, 2021 at 19:54:47 (UTC)
Goto Top
Zitat von @l.jablonski:

Wir haben mehrere Hotfolder, bei denen automatisch Dokumente rausgezogen werden und automatisch archiviert + durchsuchbar gemacht werden. Nun ist schon einige male passiert, dass der Dienst die Dateien nicht mehr verarbeitet hat, obwohl der Dienst noch lief. Deswegen können wir auch keine Dienst Überwachung nutzen.

Nun zu meiner Frage, gibt es die Möglichkeit bzw. hat jemand schon eine Lösung, wie ich meine ganzen Dateien überwachen kann mit dem erstellten Zeitstempel der Dokumente.

Schon mal FSRM angeschaut, ob dessen Funktionalität schon reicht?
Member: HansDampf06
HansDampf06 Apr 28, 2021 at 21:28:26 (UTC)
Goto Top
Auf welchem System laufen denn die Hotfolder?

Unter Linux wird das regelmäßig mit inode gelöst. Wird eine Datei geändert, erstellt, gelöscht ..., so löst inode eine Reaktion aus. Wenn in dem aufzurufenden (sh-)Script eine Zeitverzögerung mit sleep x eingebaut wird, kann das 10-min-Fenster dynamisch initialisiert werden. Freilich sollte nach dem Ablauf der Zeitverzögerung zunächst geprüft werden, ob die Datei überhaupt noch vorhanden ist, wenn das von Relevanz ist. Eine E-Mail wird sodann innerhalb des Scipts über mail abgesetzt. Insoweit alles ganz simpel.
Kommt eine Vielzahl von Dateien zur selben Zeit in Betracht, kann das dadurch kanalisiert werden, dass die Informationen zu diesen Dateien zunächst in einer temporären Datei gesammelt werden, wobei der Dateiname dieser Datei das Datum und die Urzeit (Stunde/Minute) enthält. Ein cron-Job, der jede Minute oder in einem anderen Intervall ausgeführt wird, ruft seinerseits ein zweites Script auf. Dieses zweite Script wertet alle temporären Dateien aus, die älter als die aktuelle Minute sind, und sendet in Abhängigkeit vom Ergebnis der Auswertung eine E-Mail. Die ausgewerteten temporären Dateien werden nach der Auswertung gelöscht.

Der Ansatz ist schnell umgesetzt und funktioniert sicher. Er lässt sich im Fehlerfall auch sehr gut debuggen oder überhaupt mit logging ergänzen.

Ein ähnlicher Ansatz ist mit einem FileSystemWatcher unter Windows möglich, was dem inode unter Linux entspricht.
Das kann beispielsweise in eine Webanwendung auf einem IIS, die ständig in Betrieb ist - das heißt, der Arbeitsprozess ist immer aktiv -, integriert werden. So kann der FileSystemWatcher über einen Namespace/Class beim Start des Arbeitsprozess initialisiert werden. In den Funktionen für den FileSystemWatcher ist die benötigte Reaktionsfunktionalität integriert. In dieser Art reagiert hier eine Webanwendung auf Ablagen in einem zentralen Posteingangsordner. Das "Geile" daran ist, es funktioniert auch dann, wenn das zu überwachenden Verzeichnis auf einer Netzwerkfreigabe (=/= IIS-Server) gehostet wird - das hostende Betriebssystem ist dabei "Wurscht", jedenfalls Linux oder Windows funktioniert.
Weil es sich beim FileSystemWatcher um eine Systemfunktion handelt, sollte sich das gleichsam über einen persistenten Dienst realisieren lassen. Diese Variante ist hier aber bisher mangels Erfordernis nicht verfolgt worden.

Viel Erfolg und eine gute Nacht
HansDampf06
Member: l.jablonski
l.jablonski Apr 29, 2021 at 05:56:41 (UTC)
Goto Top
Hallo Hans Dampf,

die System laufen auf einem Windows Server 2019.
Ich danke dir für deine Antwort, habe nur keine Erfahrung mit dem FileSystemWatcher ich schau es mir mal an und gebe Feedback ob es geklappt hat.
Member: HansDampf06
HansDampf06 Apr 29, 2021 at 06:21:28 (UTC)
Goto Top
Zitat von @l.jablonski:

die System laufen auf einem Windows Server 2019.

Gerade solche Aufgabenstellungen wie Deine lassen sich unter Linux sehr schnell und mit relativ wenig Aufwand lösen. Daher bietet es sich durchaus an, darüber nachzudenken, entsprechende Datenverzeichnisse von Windows Server auf einen Linux-Samba-Member zu migrieren. Das ist kein Hexenwerk, und zwar erst recht nicht, wenn alles virtualisiert ist.

Viele Grüße
HansDampf06
Member: l.jablonski
l.jablonski Apr 29, 2021 at 07:08:07 (UTC)
Goto Top
Ich danke dir für deine Antwort, ich bin leider nur nicht so Powershell erfahren.

Ich habe momentan folgendes Skript:
Get-Item C:\Ueberwachung | Foreach {$_.LastWriteTime} Damit zeigt er mir die Datei + die Zeit erfolgreich an, nur sobald ich probiere:
Get-Item C:\Ueberwachung | Foreach {$_.LastWriteTime} -gt (Get-Date).AddMinutes(-10)

bekomme ich immer Fehlermeldungen, auch meine Versuche mit anderen Syntaxen war nicht so erfolgreich.

Könntest du mir sagen, wo mein Fehler liegt oder mir ein Beispielskript zeigen bitte.

Ich danke dir für deine Rückmeldung!

Gruß

Luis
Member: HansDampf06
HansDampf06 Apr 29, 2021 at 08:10:49 (UTC)
Goto Top
Schaue Dir Deinen Befehl noch einmal genau an. @em-pie benannte den Befehl Get-ChildItem

Viele Grüße
HansDampf06
Member: em-pie
em-pie Apr 29, 2021 updated at 10:56:49 (UTC)
Goto Top
Moin,

OK - als erstes ist es immer hilfreich, die Fehlermeldung zu kennen face-smile

dann könnte es so aussehen:
$myPath = 'c:\tmp\FolderToWatch'  
$CurDt = Get-Date

# du musst ein -le nehmen, da du ja Dateien haben willst, die älter denn 10 Minuten sind
$Files = Get-ChildItem -Path $myPath | Where-Object{($_.LastWriteTime -le $CurDate.AddMinutes(-10)}

ForEach ($file in $Files) {
 #Hier wäre dann deine Aktion zu platzieren, z.B. "Sende Mail) 

# durch das Break sollte die Schleife beendet werden, was sinnvoll ist, wenn du nur eine Mail für alle gefundenen Dateien erhalten willst
 break
}

das ganze ist ungetestet und mit meinem derzeit noch rudimentärem PS-Wissen gebastelt
Member: l.jablonski
l.jablonski Apr 30, 2021 at 06:16:46 (UTC)
Goto Top
Moin,

danke dir erstmal.

Als erstes habe ich deine Methode mit $myPath = 'c:\tmp\FolderToWatch' probiert und halt dementsprechend meinen Pfad: $myPath = 'C:\Ueberwachung' leider hat er mir, dann nur meine Powershell Datei angezeigt.

Dann habe ich probiert das ganze etwas umzubauen, sieht nun wie folgt aus:
Get-ChildItem -Force C:\Ueberwachung
$Files = Get-ChildItem -Path C:\Ueberwachung | Where-Object{($_.LastWriteTime -le $CurDate.AddMinutes(-10))}

Nun Zeigt er mir die Datei an mit entsprechender LastWriteTime, bringt aber folgende Fehlermeldung:
PS C:\Users\l.jablonski\Desktop> C:\Users\l.jablonski\Desktop\Test.ps1


Verzeichnis: C:\Ueberwachung


Mode LastWriteTime Length Name
------------- ------ ----
-a---- 28.04.2021 16:03 0 test.txt
Es ist nicht möglich, eine Methode für einen Ausdruck aufzurufen, der den NULL hat.
In C:\Users\l.jablonski\Desktop\Test.ps1:2 Zeichen:61

back-to-top... chung | Where-Object{($_.LastWriteTime -le $CurDate.AddMinutes(-10))}

back-to-top~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

+ CategoryInfo : InvalidOperation: (face-smile , RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

Bei meinem ersten versuch hat noch eine ) gefehlt, aber bei dem Fehler sagt er mir ja schlicht, das mein Skript fehlerhaft ist.

Liegt des am zweimal Get-ChildItem?

Dann habe ich es wie folgt probiert:
Get-ChildItem -Force C:\Ueberwachung
Where-Object{($_.LastWriteTime -le $CurDate.AddMinutes(-10))}

Dann funktioniert alles soweit, siehe:
PS C:\Users\l.jablonski\Desktop> C:\Users\l.jablonski\Desktop\Test.ps1


Verzeichnis: C:\Ueberwachung


Mode LastWriteTime Length Name
------------- ------ ----
-a---- 28.04.2021 16:03 0 test.txt

Bedeutet des, das alle geklappt hat? Dann müsste ich mir ja nur noch anschauen, wie ich eine Aktion mit Sende Mail aktiviere.

ForEach ($file in $Files) {sende Mail
#Hier wäre dann deine Aktion zu platzieren, z.B. "Sende Mail)

  1. durch das Break sollte die Schleife beendet werden, was sinnvoll ist, wenn du nur eine Mail für alle gefundenen Dateien erhalten willst
break
}
Weil mit Sende Mail, muss er ja noch wissen woher und wie.


Danke für euer Feedback :D
Member: em-pie
em-pie Apr 30, 2021 at 07:19:48 (UTC)
Goto Top
Moin,

na es wird.
Eine Bitte: kannst du bitte doe Code-Tags hier nutzen.
< code >
myCode
< / code > (ohne die Leerzeichen)

dann ist das alles besser lesbar.

für dein Sendmail:
https://www.windowspro.de/script/send-mailmessage-e-mails-versenden-powe ...

Gruß
em-pie
Member: l.jablonski
l.jablonski Apr 30, 2021, updated at May 04, 2021 at 11:47:54 (UTC)
Goto Top
Moin,

Danke dir, Mail Versand geht. Habe es in einem seperaten Skript getestet nur momentan besteht noch ein Problem mit der Zeiterkennung, weil z.B. das Dokument von gestern von 16.03 hat ihn nicht angeregt eine E-Mail zu senden.
Daraufhin habe ich neue Dokumente angelegt um zu testen, ob es an meinem Dokument liegt nur leider auch hier keine Reaktion.

Get-ChildItem -Force C:\Ueberwachung
Where-Object{($_.LastWriteTime -le $CurDate.AddMinutes(-10))}

$PSEmailServer = "192.168.0.99"  
ForEach ($file in $Files) {Send-MailMessage -to "test@test.de" -from "PowerShell <ps@boyn.eu>" -Subject "Hotfolder Alarm" -body "Dateien werden nicht bearbeitet"  

 break
}

Er zeigt mir dann alle Dokumente an:
Verzeichnis: C:\Ueberwachung


Mode LastWriteTime Length Name
------------- ------ ----
-a---- 30.04.2021 09:39 0 asdsad.pptx
-a---- 30.04.2021 09:39 0 sadsada.docx
-a---- 30.04.2021 09:39 0 sadsadsadsad.txt
-a---- 28.04.2021 16:03 0 test.txt

Er meldet leider nie eine Mail, wahrscheinlich weil die Aktion mit dem Zeitvergleich nicht richtig funktioniert.

Fehlt im eventuell noch ein Parameter zum vergleichen der aktuellen Systemzeit?

Ich danke dir!

Gruß

Luis
Member: em-pie
Solution em-pie Apr 30, 2021 updated at 18:39:08 (UTC)
Goto Top
Edit: anonymisiere mal deine Daten in deinem Code oben face-wink

Also der Code hier klappt in einer Windows-Server 2016er Umgebung fehlerfrei:
#Set Variables
$WatchFolder = 'D:\Scripting\tmp'  
$CurTimeStamp = Get-Date
$FileAge = 10 #in Minutes

$PSEmailServer = 'your.mail.srv'  
$Sender = 'PowerShell@mail.srv'  
$Receipt = 'the1andOnly@mail.srv'  


#Get Files older then defined Age
$Files = Get-ChildItem -Path $WatchFolder | Where-Object{($_.LastWriteTime -le $CurTimeStamp.AddMinutes(-1 * $FileAge))}

#For every File...
ForEach ($File in $Files) {
    Write-Host " " $File " - " $File.LastWriteTime  
    ## ...send an E-Mail...
    Send-MailMessage -to $Receipt -from $Sender -Subject "Hotfolder Alarm" -body "Dateien werden nicht bearbeitet"  
    
    ## ...but stop after first match
    break
    }

Über die Länge des Codes mag man streiten. Geht sicherlich kürzer und schöner, aber es ist funktional face-smile

Ggf. sollte man noch via try...catch... Fehler abfangen etc. aber für einen ersten Testlauf so nutzbar
Member: l.jablonski
l.jablonski May 03, 2021 at 06:24:32 (UTC)
Goto Top
Ok danke dir ich Probier heute mal mein Glück, bei den Mail-Daten steht nichts drin was irgendwem was bringen würde. Deswegen habe ich sie auch noch drin gelassen face-smile

Grüße
Member: l.jablonski
l.jablonski May 04, 2021 at 11:58:55 (UTC)
Goto Top
Danke dir Mega hat alles auf Anhieb funktioniert. Nur noch eine Frage for each ist ja eine Schleife, bedeutet er führt des Skript nach dem er einen Fehler gefunden hat wieder neu aus? Oder muss ich jetzt eine andere Schleife einbauen, damit quasi des Skript die ganze Zeit läuft.

Danke dir für deine Antwort
Grüße
Member: em-pie
Solution em-pie May 04, 2021 at 12:03:17 (UTC)
Goto Top
Gibt mehrere Wege.
Du kannst das Script als *.ps1 abspeichern und dann als geplanten Task im 10-Minuten-Takt laufen lassen....

Gruß
em-pie
Member: l.jablonski
l.jablonski May 04, 2021 at 12:13:57 (UTC)
Goto Top
Top ich danke dir!

Dann teste ich des mal in der Praxis aus :D

Grüße
Member: l.jablonski
l.jablonski May 04, 2021 updated at 14:14:08 (UTC)
Goto Top
Noch zwei letzte Fragen, ich habe es getestet es geht auch ein UNC Pfad wie:
\\dcsrv\public\Scanner-Eingang

Was wäre wenn der Pfad nicht von allen Usern genutzt werden kann. Kann ich dem Watchfolder auch Authentifizierungs Daten mitgeben? Oder nimmt er automatisch meine Benutzer credentials, weil ich hätte genug Rechte für diesen Pfad.

Schließt der Pfad: \\dcsrv\public\Scanner-Eingang auch alle Unterordner in diesem Scaner-Eingang ein? Oder muss ich meinem Skript noch folgendes Mitgeben: \\dcsrv\public\Scanner-Eingang\* , leider sehe ich bei Aktivierung des Skriptes nicht, wo er genau sucht.

Wäre es auch möglich einen trigger einzubauen anstatt Send-Mail sowas wie restart_service... damit wäre das Skript dann komplett automatisch,

Danke dir!

Grüße