Jak sprawdzać co 30 minut, czy plik został zmodyfikowany?
Skrypciarze odpowiadają na Wasze pytania
Witamy w rubryce TechNet, w której Skrypciarze z firmy Microsoft odpowiadają na częste pytania dotyczące używania skryptów w administracji systemu. Jeśli macie jakieś pytania z tej dziedziny, zachęcamy do wysłania e-maila na adres: scripter@microsoft.com. Nie możemy zagwarantować odpowiedzi na każde otrzymane pytanie, ale staramy się jak możemy. |
Jak sprawdzać co 30 minut, czy plik został zmodyfikowany?
Cześć, Skrypciarze! W jaki sposób monitorować plik dziennika aplikacji i wysyłać alarm, jeśli sygnatura czasowa nie zmieni się w ciągu 30 minut?
--JA
Cześć, JA. Strajku anegdotowego dzień trzeci. Jest trudno – żuję paznokcie, by powstrzymać się od zalania Was serią znakomitych anegdot i historii, jakie przychodzą mi do głowy, ale będę twardy. Trzeba walczyć o swoje prawa i godność. Lada dzień Redaktorka ugnie się przed słusznymi żądaniami, jakie jej stawiam przy Waszym, czyli czytelników, poparciu. Tymczasem zajmijmy się skryptem:
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colFiles = objWMIService.ExecQuery _
("Select * from CIM_Datafile Where Name = 'C:\\Scripts\\Application.log'")
For Each objFile in colFiles
strOriginalTimestamp = objFile.LastModified
Next
Wscript.Echo "Monitoring application log file: " & Now
Wscript.Echo
Do While True
Wscript.Sleep 1800000
Set colFiles = objWMIService.ExecQuery _
("Select * from CIM_Datafile Where Name = 'C:\\Scripts\\Application.log'")
For Each objFile in colFiles
strLatestTimestamp = objFile.LastModified
Next
If strLatestTimestamp <> strOriginalTimestamp Then
strOriginalTimestamp = strLatestTimeStamp
Else
Wscript.Echo "ALERT: " & Now
Wscript.Echo "The application log file has not been modified in the last 30 minutes."
Wscript.Echo
strOriginalTimestamp = strLatestTimeStamp
End If
Loop
Zobaczmy, jak to właściwie działa. Na początek łączymy się z usługą WMI na komputerze lokalnym. Była to jedna z pierwszych decyzji, jakie musieliśmy podjąć: czy wykonamy to zadanie za pomocą WMI, czy uciekniemy się do zastosowania innej technologii, np. FileSystemObject? Zdecydowaliśmy się na zastosowanie WMI z jednego, prostego powodu – będziemy mogli dzięki temu napisać skrypt monitorujący plik dziennika na komputerze zdalnym z taką samą łatwością, co na komputerze lokalnym. Chcemy wykonać to zadanie na zdalnym komputerze atl-fs-01? Żaden problem – wystarczy przypisać tę nazwę zmiennej strComputer:
strComputer = "atl-fs-01"
Kolejnym krokiem jest określenie, kiedy plik został ostatnio zmodyfikowany. Musimy poznać bieżącą wartość właściwości LastModified, aby sprawdzić, czy uległa ona (a zarazem i sam plik) zmianie w ciągu ostatnich 30 minut. W tym celu używamy najpierw poniższego wiersza kodu, by pobrać wszystkie wystąpienia klasy CIM_Datafile, których właściwość Name (oznaczająca ścieżkę) ma wartość C:\\Scripts\\Application.log:
Set colFiles = objWMIService.ExecQuery _
("Select * from CIM_Datafile Where Name = 'C:\\Scripts\\Application.log'")
Nie, to nie pomyłka – powinno tam być C:\\Scripts\\. Ze względu na to, że \ jest w WMI znakiem zastrzeżonym, każdy taki znak musi zostać oznaczony – w tym celu używa się drugiego znaku \.
Po nawiązaniu połączenia uruchamiamy pętlę For Each, która przechodzi przez kolekcję plików zwróconych przez kwerendę (jak zapewne sami wiecie, w naszej kolekcji może być tylko jeden plik). Następnie za pomocą poniższego wiersza kodu przypisujemy wartość właściwości LastModified do zmiennej o nazwie strOriginalTimestamp:
strOriginalTimestamp = objFile.LastModified
Wszystko to było jedynie wstępem – teraz musimy się dopiero zabrać do prawdziwej pracy. W tym celu uruchamiamy pętlę Do While, która będzie działać po wiek wieków (a przynajmniej dopóki wartość True się nie zmieni):
Do While True
Od czego zaczynamy działanie wewnątrz pętli? W pewnym sensie, od niczego. Wywołujemy metodę Sleep i wstrzymujemy działanie skryptu na pół godziny:
Wscript.Sleep 1800000
Uwaga:
Dla jasności – 1800000 oznacza 1 800 000 milisekund. W sekundzie jest 1 000 milisekund; w minucie – 60 000 milisekund; w 30 minutach jest więc 1 800 000 milisekund (1 000 x 60 x 30).
Po upływie 30 minut ponownie sprawdzamy bieżącą wartość właściwości LastModified; w tym celu ponownie łączymy się z plikiem i przechowujemy wartość właściwości LastModified w zmiennej o nazwie strLatestTimestamp:
strLatestTimestamp = objFile.LastModified
Dochodzimy teraz do tego wiersza kodu:
If strLatestTimestamp <> strOriginalTimestamp Then
Co tutaj robimy? No cóż, porównujemy pierwotną sygnaturę czasową z obecną. Załóżmy, że się one od siebie różnią. O czym to może świadczyć? Tylko o jednym: plik musiał zostać zmodyfikowany w ciągu ostatnich 30 minut. Dlatego też po prostu przypisujemy bieżącą sygnaturę czasową (strLatestTimestamp) zmiennej strOriginalTimestamp, ponownie uruchamiamy pętlę i czekamy kolejne pół godziny.
To było łatwe. Co jednak się stanie, jeśli obie sygnatury są takie same? Ponownie interpretacja może być tylko jedna – plik nie został zmodyfikowany w ciągu ostatnich 30 minut. W takim wypadku używamy poniższych wierszy kodu, by wyświetlić w oknie polecenia odpowiedni komunikat (podobnie jak większość skryptów monitorowania, i ten zdecydowanie najlepiej uruchomić w hoście skryptów CScript (j.ang.):
Wscript.Echo "ALERT: " & Now
Wscript.Echo "The application log file has not been modified in the last 30 minutes."
Wscript.Echo
Da to nam następujący komunikat:
ALERT: 7/20/2007 1:26:35 PM
The application log file has not been modified in the last 30 minutes.
Następnie przypisujemy bieżącą sygnaturę czasową do zmiennej strOriginalTimestamp, ponownie uruchamiamy pętlę, pauzujemy na pół godziny, po czym ponawiamy test. Proces ten będzie się powtarzać bez końca, chyba że użytkownik przerwie skrypt lub zamknie okno poleceń.
Rozumie się chyba samo przez się, że nie musimy ograniczyć się tylko do wyświetlenia komunikatu. Można np. wysłać e-mail, zapisać zdarzenie w dzienniku albo zrobić cokolwiek innego.
To już wszystko na dziś. To zaskakujące, ale Redaktorka ciągle jeszcze nie przyszła na kolanach błagać o wybaczenie. Jestem rozczarowany postawą czytelników – najwyraźniej przyszło za mało wiadomości protestacyjnych. Aby ułatwić Wam ich słanie, podaję poniżej adres:
Skrypciarz piszący artykuły skrypciarskie
Microsoft Corporation
Building 42/4039
Redmond, WA 98052
Do początku strony |