Centrum skryptów - Systemy operacyjne

Jak monitorować liczbę plików w folderze?

Udostępnij na: Facebook

Skrypciarze odpowiadają na Wasze pytania

Cześć Skrypciarze!

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 monitorować liczbę plików w folderze?

Cześć Skrypciarze! Pytanie

Cześć, Skrypciarze! Używamy pewnej aplikacji niezależnej firmy, która z reguły się nie psuje, ale kiedy już się zepsuje, to bardzo poważnie zakłóca pracę naszej firmy. Zawsze jednak możemy z całą pewnością stwierdzić, kiedy aplikacja jest bliska awarii; w takim momencie jeden z jej katalogów zaczyna zapełniać się plikami dziennika. Co mamy zrobić, żeby otrzymywać powiadomienie za każdym razem, gdy liczba plików dziennika w tym folderze przekroczy określoną wartość?

-- AE

Cześć Skrypciarze! Odpowiedź

Cześć, AE. Zanim przejdziemy do odpowiedzi na to pytanie, chcemy zwrócić Waszą uwagę na fakt, że niektórzy ludzie na tym świecie są po prostu uosobieniem zła. Tak, to niestety smutna prawda. Przykładów ludzkiej złośliwości nie trzeba szukać daleko, jest ich pełno w naszym codziennym życiu. Idąc do sklepu na zakupy często natykamy się na osoby, które wpychają się bezceremonialnie w kolejkę do kasy szybkiej obsługi z przekroczonym limitem produktów, parkują tak, że zajmują dwa miejsca na parkingu nie zważając na ich deficyt, wymuszają pierwszeństwo na drodze, staruszki w autobusach szantażujące wzrokiem siedzących pasażerów, przykładów można mnożyć. Piszący te słowa Skrypciarz zastanawia się nad tym, skąd ludzie biorą pomysły na takie zachowania. Nie mogą one być przecież wynikiem zimnych kalkulacji i stąd wniosek o uosabieniu zła. No bo jak inaczej wytłumaczyć takie zachowanie. Samo zło.

Naprawdę niewielu jest w dzisiejszym świecie ludzi, którzy są mili dla otoczenia, nikomu nie sprawiają przykrości i z uśmiechem na twarzy odpowiadają na zadane im pytania. Do takich właśnie osób należy nasz Skrypciarz, który nie może posiąść się ze szczęścia, mając szansę odpowiedzieć na pytanie dotyczące skryptu monitorującego liczbę plików w folderze:

strComputer = "."



Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")



Do While True

    Set colFileList = objWMIService.ExecQuery _

        ("ASSOCIATORS OF {Win32_Directory.Name='C:\Logs'} Where " _

            & "ResultClass = CIM_DataFile")



    If colFileList.Count >= 100 Then

        Exit Do

    End If



    Wscript.Sleep 60000

Loop



Wscript.Echo "There are at least 100 log files in the target folder."

W zasadzie istnieje kilka sposobów rozwiązania tej zagadki; wybraliśmy ten, który wydaje nam się najłatwiejszy do zrealizowania przy użyciu skryptu i najprostszy do zrozumienia. Rozpoczynamy od połączenia się z usługą WMI na lokalnym komputerze, chociaż równie dobrze moglibyśmy monitorować folder znajdujący się na komputerze zdalnym; w takim przypadku wystarczy przypisać nazwę tego komputera (np. arl-fs-01) do zmiennej o nazwie strComputer:

strComputer = "atl-fs-01"

Następnie uruchamiamy pętlę Do While, która będzie działać bez końca (lub przynajmniej dopóki wartość True jest równa True):

Do While True

Nie ma się co martwić zawczasu; to tylko wygląda jak pomyłka z naszej strony. Jak zaraz sami zobaczycie, nasza pętla zawiera lukę umożliwiającą nam zakończenie jej działania.

Dla potrzeb naszego skryptu zdecydowaliśmy, że wartością wyzwalającą powiadomienie będzie 100: jeżeli w naszym folderze docelowym (C:\Logs) znajdzie się więcej niż 100 plików, powinniśmy otrzymać powiadomienie. A to dobre pytanie: skąd w ogóle będziemy wiedzieć, ile plików znajduje się w folderze C:\Logs? No cóż, prostym sposobem by to określić jest zastosowanie następującego zapytania WMI, które da nam kolekcję zawierającą wszystkie pliki znajdujące się w folderze C:\Logs:

Set colFileList = objWMIService.ExecQuery _

    ("ASSOCIATORS OF {Win32_Directory.Name='C:\Logs'} Where " _

        & "ResultClass = CIM_DataFile")

Przyznajemy, że składnia jest tu bądź co bądź dziwna. Tak naprawdę jednak szukamy tu po prostu elementów powiązanych z konkretnym wystąpieniem klasy Win32_Directory. (Których wystąpień? Tych, które posiadają właściwość NameC:\Logs.) Oczywiście interesują nas tylko elementy będące wystąpieniami klasy CIM_DataFile; jak się pewnie domyślacie, jeżeli coś jest wystąpieniem klasy CIM_DataFile, to musi być plikiem. Jest to trochę okrężna droga, ale w ten sposób WMI przekazuje kolekcję wszystkich plików znajdujących się w danym folderze. Jeżeli pliki znajdują się w innym folderze, cóż, wtedy należałoby zastąpić ścieżkę C:\Logs ścieżką dostępu do tego folderu.

Jak się okazuje, ciekawe w kolekcji WMI jest to, że ma ona zawsze właściwość o nazwie Count; mówi nam ona, ile elementów (w tym przypadku: ile plików) znajduje się w kolekcji. Stąd nasz następny wiersz kodu, który sprawdza, czy wartość właściwości Count jest większa lub równa 100:

If colFileList.Count >= 100 Then

Uwaga. A co, jeżeli nasza wartość docelowa to nie 100, a 10, 10 000 lub jakakolwiek inna liczba? Nic prostszego; wystarczy tylko zmienić wartość 100 na żądaną liczbę.

Przypuśćmy, że właściwość Count jest mniejsza niż 100; co się wtedy stanie? No cóż, w takim wypadku zatrzymujemy skrypt na 60 sekund (60 000 milisekund):

Wscript.Sleep 60000

Kiedy minie jedna minuta, uruchamiamy pętlę i ponownie wysyłamy kwerendę do folderu C:\Logs i jeszcze raz sprawdzamy, ile jest plików w tym folderze. Tak, naprawdę musimy ponownie wysyłać kwerendę za każdym razem; to jedyny sposób, żeby poznać aktualną liczbę plików w tym folderze.

Oznacza to także, że co minutę sprawdzamy, czy liczba plików w folderze C:\Logs przekroczyła wartość docelową 100. Jednak możemy także zmienić tę wartość na dowolną inną. Na przykład, może 60 sekund to za długo; może folder jest w stanie zapełnić się i spowodować awarię aplikacji o wiele szybciej. OK; oto drobna modyfikacja, która spowoduje, że skrypt zatrzyma się na jedynie 15 sekund (15 000 milisekund) pomiędzy zatrzymaniami:

Wscript.Sleep 15000

Ewentualnie, być może nie ma potrzeby sprawdzania folderu co minutę; może wystarczy co 10 minut. W porządku. Jeżeli w jednej minucie jest 60 000 milisekund (a tak przecież jest), to w 10 minutach będzie 600 000 milisekund. Stąd poniższy wiersz kodu, który zatrzymuje skrypt na 10 minut pomiędzy sprawdzaniem:

Wscript.Sleep 600000

Itd.

A co się stanie, jeżeli właściwość Count będzie większa lub równa 100? W takim przypadku należy zakończyć działanie naszej „niekończącej” się pętli:

Exit Do

Kiedy zakończymy działanie pętli, wywołujemy echo powiadomienia informującego nas o tym, że wartość docelowa została przekroczona:

Wscript.Echo "There are at least 100 log files in the target folder."

Szczerze mówiąc, nie musimy kończyć działania pętli; zrobiliśmy to tylko po to, żeby nie otrzymywać powiadomienia o przekroczeniu wartości co minutę. To jest zaleta zakończenia działania pętli: nie ma uporczywych komunikatów. A wada? Po ponownym uruchomieniu aplikacji (lub innej czynności mającej na celu zapobieżenie awarii) musimy także ponownie uruchomić skrypt monitorujący. Jeżeli nie przeszkadzają nam powtarzające się powiadomienia, można tak napisać skrypt, że będzie działał (i wysyłał nam powiadomienia) nawet po osiągnięciu wartości docelowej:

strComputer = "."



Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")



Do While True

    Set colFileList = objWMIService.ExecQuery _

        ("ASSOCIATORS OF {Win32_Directory.Name='C:\Logs'} Where " _

            & "ResultClass = CIM_DataFile")



    If colFileList.Count >= 100 Then

        Wscript.Echo "There are at least 100 log files in the target folder."

    End If



    Wscript.Sleep 60000

Loop

Należy także wspomnieć, że nie musimy się ograniczać do zastosowania skryptu WScript jako sposobu na wydawanie powiadomień. Na przykład, możemy chcieć wpisać zdarzenie do dziennika zdarzeń danej aplikacji (j.ang.), lub wysłać wiadomość e-mail (j.ang.), używając usługi SMTP. To zależy tylko od naszej woli.

Oczywiście byłoby pięknie, gdyby skrypt mógł naprawić aplikację za nas. Nie możemy podać żadnego skryptu o takim działaniu, ponieważ nie wiemy nic na temat tej aplikacji. Jednak możliwe jest, żeby skrypt wyłączał i uruchamiał ponownie aplikację; to zależy od jej rodzaju. (Bez wątpienia możemy zakończyć proces aplikacji, a następnie uruchomić ją ponownie. Jednak w zależności od aplikacji, mogłoby to spowodować więcej problemów niż byśmy chcieli.)

Mamy nadzieję, że to pomoże, AE. Mamy również nadzieję, że Twoja wiara w ludzkość nie została zachwiana, jak to się stało w przypadku piszącego te słowa Skrypciarza. Jakby tego było mało, kiedy dziś rano wrócił do pracy, wstąpił do kuchni i wziął plastikową łyżeczkę z torebki z napisem Plastikowe łyżeczki, kiedy usiadł przy swoim biurku z zamiarem spałaszowania swojego ulubionego jogurtu truskawkowego zdał sobie sprawę, że w ręce trzyma widelec: ktoś włożył plastikowy widelec do torebki z napisem Plastikowe łyżeczki. Zło, zło wcielone.

 Do początku strony Do początku strony

Centrum skryptów - Systemy operacyjne