Hallo,
ich habe hier einen Linux Fileserver wo viele Mitarbeiter über Samba unter Windows ihre Daten ablegen. Um Alte Daten die älter als 1 Monat sind zu archivieren, habe ich ein Script mit autoIt programmiert. Das Skript loggt jeden Abend den Zeitpunkt, wann das letzte Mal auf die Datei zugegriffen wurde. Das muss leider jeden Abend geschehen, da das Alter der Datei nicht aussagekräftig ist. Desweiteren wird bei der abendlichen Datensicherung jede Datei "angefasst" sodass der letzte Zeitpunkt des Zugriffes verfälscht wird. Dafür halt das AutoIt Script.
Soviel zur Vorgeschichte. Da ich nun nicht jeden Abend um 20 Uhr das Skript von Hand starten möchte habe ich Windows Boardmittel genutzt und einen geplanten Task angelegt der die .exe ausführt. Augenschaeinlich funktioniert es auch. Aber nicht zu 100%. Es befinden sich ca. 4500 Dateien auf dem Server bzw. in dem Laufwerk worauf zugegriffen wird. Nach der abendlichen Auswertung werden Dateipfad + letzter Zugriffszeitpunkt in eine .csv-Datei geschrieben, die am nächsten Tag für die nächste Auswertung wieder eingelesen wird.
Ist die Auswertung gelaufen wird das Ergebnis wieder in die Datei geschrieben. Wurde die .exe allerdings über den geplanten Task gestartet, so werden immer so 30-50 Dateien weniger in die .csv geschrieben, als vorhanden sind. So werden die vorhandenen Dateien von Tag zu Tag immer weiter reduziert! Starte ich die .exe manuell, ist alles einwandfrei! Keine fehlenden Dateien in der .csv!
Das Skript läuft auf einem alten Server mit 800Mhz, die Auswertung dauert knapp 40 min. wenn es per geplanten Task gestartet wurde. Starte ich das Skript auf dem gleichen Server von hand dauerts ca. 6 Minuten. Wie kann das bitte sein?
Hier mal das Skript (Beschreibung zu den einzelnen Zeilen stehen weiter rechts
Spoiler anzeigen
#include <GuiConstantsEx.au3>
#include <WinAPI.au3>
#include <Date.au3>
#include <WindowsConstants.au3>
#Include <File.au3>
#include <array.au3>
#Include <Date.au3>
;Start: 1. September 2011
[/autoit] [autoit][/autoit] [autoit]$datumheute = @YEAR & "/" & @MON & "/" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC ;Braucht man so formatiert für _DateDiff
global $nichtloeschen = "\\yf7sltja\zentral\bnk\d_edv\AutoIT\Bereinigung Laufwerk H\diese dateien nicht löschen.txt"
global $log = "\\yf7sltja\zentral\bnk\d_edv\AutoIT\Bereinigung Laufwerk H\log.txt"
global $aNichtloeschen
global $archiv = "\\yf7sltja\zentral\bnk\d_edv\AutoIT\Bereinigung Laufwerk H\Archiv_30 Tage"
global $io = 0 ;diese ariable dient zur temporären Speicherung einer information. siehe weiter unten.
global $aAuswertung
Global $auswertung = "\\yf7sltja\zentral\bnk\d_edv\AutoIT\Bereinigung Laufwerk H\auswertung.csv"
_FileReadToArray($nichtloeschen, $aNichtloeschen)
if not FileExists($auswertung) Then ;Existiert die Auswertungsdatei noch nicht, dann...
$aDateien = _GetFilesFolder_Rekursiv('.', -1, 0)
for $k = 1 to ubound($aDateien) - 1
$neu = StringTrimLeft($aDateien[$k], 2) ;Die Daten im Array werden für die Verarbeitung angepasst
$aDateien[$k] = "\\yf7sltja\zentral\bnk\d_global" & $neu
Next
_filecreate($auswertung) ;Wird sie erstellt...
dim $aAuswertung[ubound($aDateien)][2] ;Dann wird das Array der Größe des $aDateienarrays angepasst...
for $c = 1 to ubound($aDateien) - 1 ;und anschliessend die Inhalte von einem Array ins andere übertragen
$aAuswertung[$c][0] = $aDateien[$c]
$aAuswertung[$c][1] = $datumheute ;schreibt nach der Erstellung das Datum von heute als letzter Zugriff...
Next
fileopen($auswertung, 2)
for $b = 1 to ubound($aAuswertung) - 1
FileWrite($auswertung, $aAuswertung[$b][0] & ";" & $aAuswertung[$b][1] & @CRLF) ;Schreibt Array in Datei *1
Next
fileclose($auswertung)
Exit ;und das Skript wird dann beendet
Else
Global $h = FileOpen($auswertung, 0)
Global $aAuswertung = _CSV2Array($h, Default, True, 1) ;Existiert die Datei bereits, wird diese in ein Array aufgenommen.
_ArrayDelete($aAuswertung, ubound($aAuswertung)) ;Löscht den letzten Eintrag im Array, da dieser leer ist. Der wird von dem mit *1 markierten @crlf verursacht
;Vll. werden nicht alle Daten aus der auswertung.csv vom Vortag eingelesen!!!!!!!!!!!!!
EndIf
$aDateien = _GetFilesFolder_Rekursiv('.', -1, 0) ;Neue Dateien müssen ab hier nun dem vorhandenen Array hinzugefügt werden
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit];---------------------------------------------
global $pfadtest = "\\yf7sltja\zentral\bnk\d_edv\AutoIT\Bereinigung Laufwerk H\test.txt"
FileOpen($pfadtest, 2)
FileWrite($pfadtest, ubound($aAuswertung) & " Inhalt der eingelesenen Auswertung.csv" & @CRLF)
For $i = 0 to ubound($aDateien) -1
FileWrite($pfadtest, $aDateien[$i] & @CRLF)
Next
FileClose($pfadtest)
;~ MsgBox(1, "lala", "lala")
;---------------------------------------------
for $k = 1 to ubound($aDateien) - 1 ;Wiederholtes vorbereiten der neu eingelesenen Daten für die Verarbeitung.
$neu = StringTrimLeft($aDateien[$k], 2)
$aDateien[$k] = "\\yf7sltja\zentral\bnk\d_global" & $neu
Next
for $i = 1 to ubound($aDateien) - 1
$search = _ArraySearch($aAuswertung, $aDateien[$i]) ;Such in $aAuswertung (Der Auswertung vom Vortag) nach den Dateien die gerade neu nach $aDateien eingelesen wurden.
if @error then ;Wird eine Datei nicht gefunden, dann wird @error gesetzt was bedeutet, dass die gerade gesuchte Datei neu ist.
redim $aAuswertung[ubound($aAuswertung) + 1][2] ;Diese neue Datei wird nun dem Array $aAuswertung hinzugefügt
$aAuswertung[ubound($aAuswertung) - 1][0] = $aDateien[$i]
$aAuswertung[ubound($aAuswertung) - 1][1] = $datumheute ;Datei ist neu. Datum von heute wird als letzter Zugriffszeitpunkt gesetzt
EndIf
Next
dim $altepfade[1] ;Array wo nachher Positionen der gelöschten Dateien reingeschrieben werden. Wird nachher für deren löschvorgang aus dem Array $aAuswertung benötigt
for $a = 1 to ubound($aAuswertung) - 1 ;Datei für Datei wird durchgegangen, wann der letzte Zugriffszeitpunkt war
if FileExists($aAuswertung[$a][0]) then
$hFile = _WinAPI_CreateFile($aAuswertung[$a][0], 2, 2, 2, 4)
$aTime = _Date_Time_GetFileTime($hFile)
_WinAPI_CloseHandle($hFile)
$letzterzugriff = _Date_Time_FileTimeToStr($aTime[1]) ;In der Variablen steht, wann das letzte Mal auf die Datei zugegriffen wurde
$letzteUhrzeit = StringRight($letzterzugriff, ;Da das letzte Zugriffsdatum + Uhrzeit falsch formatiert von der Funktion zurückgegeben wird, muss das vorher extrahiert werden
$letzteDatum = @YEAR & "/" & stringleft($letzterzugriff, 5)
if NOT $letzterzugriff = @error Then ;Ist die Datei zur Auswertung noch im Zugriff, gibt _Date_Time_FileTimeToStr @error zurück. ist das der Fall, wird die aktuelle Uhrzeit ins Array geschrieben
if $aAuswertung[$a][1] = 0 Then ;Beim ersten Durchgang ist das Array noch leer, und muss daher noch mit Datum + uhrzeit gefüllt werden
$aAuswertung[$a][1] = $letzteDatum & " " & $letzteUhrzeit
Else
$dif = _DateDiff("h", $letzteDatum & " " & $letzteuhrzeit, $datumheute) ;Steht im Array bereits was, wird das aktuelle Datum, mit dem letzten Zugriffsdatum verglich. Ist es z. B. heute um 15 Uhr gewesen, dann sind das
if $dif < 16 Then ;waren 16h ;5 Std. unterschied gewesen, somit < 16. Letzter Zugriff wird ins Array geschrieben.
$aAuswertung[$a][1] = $letzteDatum & " " & $letzteuhrzeit ;Ist die Diferenz größer, wurde zuletzt gestern gegen 23. uhr zugegriffen. Das alte Datum bleibt im Array bestehen
EndIf
EndIf
else
$aAuswertung[$a][1] = $datumheute
EndIf
Else
;~ MsgBox(1, "lala", $aAuswertung[$a][0])
ReDim $altepfade[ubound($altepfade) + 1]
$altepfade[ubound($altepfade) - 1] = $a ;schreibt den index von dem alten Pfad in das Array. Später können so die alten pfade aus dem Array dann gelöscht werden.
EndIf
Next
;------------------------------------------------
global $pfadtest1 = "\\yf7sltja\zentral\bnk\d_edv\AutoIT\Bereinigung Laufwerk H\altepfade.txt"
fileOpen($pfadtest1, 2)
;~ _arraydisplay($altepfade)
For $i = 1 to ubound($altepfade) -1
FileWrite($pfadtest1, $aAuswertung[$altepfade[$i]][0] & @CRLF)
Next
FileClose($pfadtest1)
;------------------------------------------------
;~ _arraydisplay($altepfade)
if ubound($altepfade) > 1 Then ;erst wenn min. ein Eintrag in dem Array vorhanden ist, wird der Löschvorgang gestartet. Ohne die Abfrage fürde es zu einem Bug kommen, der immer den ersten Eintrag im Array löscht was bedeuten würde, dass je Durchgang eine Datei aus dem Vergleich verschwindet
for $c = 1 to ubound($altepfade) - 1 ;Löscht die nicht mehr vorhandenen Pfade aus $aAuswertung mithilfe von dem erstellten Array $altepfade, wo sich die Indexe der alten Pfade befinden
_arraydelete($aAuswertung, $altepfade[$c])
Next
EndIf
fileopen($auswertung, 2)
for $b = 0 to ubound($aAuswertung) - 1
FileWrite($auswertung, $aAuswertung[$b][0] & ";" & $aAuswertung[$b][1] & @CRLF) ;Schreibt Array in Datei
Next
fileclose($auswertung)
FileOpen($log, 1)
for $a = 0 to ubound($aAuswertung) - 1
$dif = _DateDiff("D", $aAuswertung[$a][1], $datumheute) ;waren Tage nicht stunden ;Prüft die Diferenz in Tagen von dem letzten Zugriff bis heute
if $dif > 30 Then ;waren 30 Tage ;Wurde die Datei die letzten 30 Tagen nicht benutzt, dann wird sie verschoben
for $i = 1 to ubound($aNichtloeschen) - 1
$find = stringinstr($aAuswertung[$a][0], $aNichtloeschen[$i]) ;Der Ordner der nicht gelöscht werden soll ( z. B. \\yf7sltja\...\ausbildung) wird in dem gerade aktuellen String gesucht
if $find > 0 Then ;Wird er da gefunden, dann wird die Schleife verlassen. Mit der aktuellen Datei soll nichts passieren (soll nicht verschoben werden)
$io = 0 ;Die eventuell auf 1 gesetzte Variable (in den vorherigen Durchläufen), wird hier weider zurückgesetzt, für den nächsten Durchlauf
exitloop ;Es kann nun sein, dass ...Ausbildung... erst an 3 Stelle im Array steht. Ist das der Fall, wäre die Variable $io schon vorher 2 mal
Else ;auf 1 gesetzt wurden, weshalb diese wieder auf 0 zurückgesetzt werden muss, damit das nächste IF diese richtig handelt und die Datei nicht "anfässt"
$io = 1 ;Wurde der aktuelle String aus "nicht löschen" in dem aktuellen String aus $aAuswertung nicht gefunden, dann bedeutet das, das diese
EndIf ;Datei verschoben werden kann. Die Variable $io wird auf 1 gesetzt. Datei kann verschoben werden!
Next
if $io = 1 Then ;Wird der String in dem Array der nicht zu löschenden Dateien/Ordner gefunden, wird mit dem nächsten Arrayeintrag weitergemacht
;~ MsgBox(1, "lala", "hat funktioniert")
$struktur = stringmid($aAuswertung[$a][0], 33) ;Hier wird der Pfadname der Datei extrahiert...
$del = FileMove($aAuswertung[$a][0], $archiv & "\" & $struktur, ;war filemove(erstmal beibehalten) ;...damit bei dem Verschiebenvorgang die Ordnerhirarchie mit erstellt wird im Archiv
if @error Then ;Gibt die Funktion ein Fehler zurück, ist die Datei nicht mehr vorhanden...
_FileWriteLog($log, $aAuswertung[$a][0] & " Datei wurde bereits von User gelöscht" & @CRLF) ;...das wird dann in die Logdatei geschrieben, da der Löschvorgang vom User selber schon durchgeführt wurde...
Else ;...und der Eintrag der heute noch in der auswertung.csv vorhanden war, wird mit dem Lauf am nächsten Tag gelöscht.
_filewritelog($log, $aAuswertung[$a][0] & @CRLF) ;Ansonsten wird ein normaler Logeintrag geschrieben, mit dem Datum/Uhrzeit des Verschiebens
EndIf
$io = 0 ;Reset der Variablen für den nächsten Durchgang
EndIf
endif
Next
fileclose($log)
Func _GetFilesFolder_Rekursiv($sPath, $sExt='*', $iDir=-1, $iRetType=0, $sDelim='0')
Global $oFSO = ObjCreate('Scripting.FileSystemObject')
Global $strFiles = ''
Switch $sDelim
Case '1'
$sDelim = @CR
Case '2'
$sDelim = @LF
Case '3'
$sDelim = ';'
Case '4'
$sDelim = '|'
Case Else
$sDelim = @CRLF
EndSwitch
If ($iRetType < 0) Or ($iRetType > 1) Then $iRetType = 0
If $sExt = -1 Then $sExt = '*'
If ($iDir < -1) Or ($iDir > 1) Then $iDir = -1
_ShowSubFolders($oFSO.GetFolder($sPath),$sExt,$iDir,$sDelim)
If $iRetType = 0 Then
Local $aOut
$aOut = StringSplit(StringTrimRight($strFiles, StringLen($sDelim)), $sDelim, 1)
If $aOut[1] = '' Then
ReDim $aOut[1]
$aOut[0] = 0
EndIf
Return $aOut
Else
Return StringTrimRight($strFiles, StringLen($sDelim))
EndIf
EndFunc
Func _ShowSubFolders($Folder, $Ext='*', $Dir=-1, $Delim=@CRLF)
If Not IsDeclared("strFiles") Then Global $strFiles = ''
If ($Dir = -1) Or ($Dir = 0) Then
For $file In $Folder.Files
If $Ext <> '*' Then
If StringRight($file.Name, StringLen($Ext)) = $Ext Then _
$strFiles &= $file.Path & $Delim
Else
$strFiles &= $file.Path & $Delim
EndIf
Next
EndIf
For $Subfolder In $Folder.SubFolders
If ($Dir = -1) Or ($Dir = 1) Then $strFiles &= $Subfolder.Path & '\' & $Delim
_ShowSubFolders($Subfolder, $Ext, $Dir, $Delim)
Next
EndFunc
Func _CSV2Array($hFile, $cSeperator = "auto", $bFilterString = True, $iColumnMode = 0)
Local $s = FileRead($hFile)
If @error Then Return SetError(1)
If $cSeperator = Default Then $cSeperator = "auto"
If Not $cSeperator Then $cSeperator = Opt("GUIDataSeparatorChar")
; searching the line-seperator and splitting the lines into an array
Local $aLines
If StringInStr($s, @CRLF) Then
$aLines = StringSplit($s, @CRLF, 1)
ElseIf StringInStr($s, @CR) Then
$aLines = StringSplit($s, @CR)
Else
$aLines = StringSplit($s, @LF)
EndIf
; searching the delimiter in the first line
Local $aTMP
If $cSeperator = "auto" Then
Local $iMax = 0
Local $iC[5] = [0, 0, 0, 0, 0]
Local $sC[5] = [";", ",", @TAB, "|"]
$aTMP = StringRegExp($aLines[1], ";", 3)
If Not @error Then $iC[0] = UBound($aTMP)
For $i = 0 To UBound($sC) - 1
If $iC[$i] > $iMax Then
$iMax = $iC[$i]
$cSeperator = $sC[$i]
EndIf
Next
EndIf
; creating 2-dim array based on the number of data in the first line
$aTMP = StringSplit($aLines[1], $cSeperator)
Local $iCol = $aTMP[0]
Local $aRet[$aLines[0]][$iCol]
; splitting and filling the lines
For $i = 1 To $aLines[0]
$aTMP = StringSplit($aLines[$i], $cSeperator)
If @error Then ContinueLoop
If $aTMP[0] > $iCol Then
Switch $iColumnMode
Case 0
Return SetError(2, $i)
Case 1
ReDim $aRet[$aLines[0] - 1][$aTMP[0]]
Case 2
$aTMP[0] = $iCol
Case Else
Return SetError(3)
EndSwitch
EndIf
For $j = 1 To $aTMP[0]
$aTMP[$j] = StringStripWS($aTMP[$j], 3)
If $bFilterString Then ; removing leading and trailing " or '
$aTMP[$j] = StringRegExpReplace($aTMP[$j], '^("|'')(.*?)\1$', '$2')
EndIf
$aRet[$i - 1][$j - 1] = $aTMP[$j]
Next ; /cols
Next ; /lines
Return $aRet
EndFunc ;==>_CSV2Array