Blog: Systemy serwerowe | Windows server | Systemy microsoft | Powershell

PowerShell – jak pisać skrypty

PowerShell – jak pisać skrypty
  • 4 328 views

PowerShell pomaga zautomatyzować powtarzalne czynności i wykonać je szybciej, dzięki czemu administratorzy mogą się skupić na innych zadaniach.

Udostępnij!

Problem jaki się często pojawia ze skryptami PowerShell jest taki, że skrypty robią zbyt wiele rzeczy i są trudne do modyfikacji – nawet przez autora danego skryptu. Spotkałem się z tym u jednego z klientów gdzie proces zakładania kont użytkownikom przestał odpowiadać potrzebom biznesowym i po założeniu konta użytkownikowi, była potrzeba nanoszenia licznych poprawek. Próba rozwiązania zaistniałego problemu u podstaw czyli przy zakładaniu kont dla użytkowników okazała się być niemożliwa do przeprocesowania. na pytanie w czym jest problem – usłyszałem – „Paweł, tego nie robią ludzie tylko skrypt, a ten skrypt ma ponad 1000 linii kodu. Nikt się nie odważy go poprawić.”

W czym więc był problem skoro do tej pory skrypt działał, a teraz to co skrypt robi jest niewystarczające i wymaga dodatkowego nakładu pracy?

Projektowanie narzędzi

Skrypt ma wykonać jedną czynność

Przeanalizujmy jak są skonstruowane polecenia PowerShell na przykładzie poleceń dotyczących serwisów.

Get-Command -Noun *service* -Module "Microsoft.PowerShell.Management" | Select-Object name
Get-Service       
New-Service       
New-WebServiceProxy
Restart-Service   
Resume-Service    
Set-Service      
Start-Service     
Stop-Service      
Suspend-Service

Jak można zauważyć jest polecenie do pozyskiwania informacji na temat serwisów „Get-Service” jak i zatrzymywanie „Stop-Service”, uruchamiania „Start-Service” czy modyfikowania „Set-Service”. Każde z tych poleceń robi jedną rzecz.

Wyobraźmy sobie, że mamy do napisania skrypt tworzący raport na temat komputerów i zainstalowanego systemu operacyjnego. raport ma zawierać informację na temat:

  • Nazwa komputera
  • Producent
  • Model
  • Wersja systemu operacyjnego i numer kompilacji
  • Typ Procesora
  • Wolne miejsce na dysku systemowym (zwykle C: ale nie zawsze)

Nasz skrypt będziemy chcieli uruchamiać tak by pozyskać informację z komputerów firmowych (desktopów i laptopów). Co to znaczy, że skrypt ma robić jedną czynność?

Nasz skrypt robiący raport na temat komputerów musimy rozbić na podstawowe czynności np:

  • pozyskanie danych
  • budowa raportu.

By zbudować raport muszę mieć dane. Więc jedna funkcja będzie pozyskiwała dane z komputerów, a druga na podstawie zebranych danych przygotowywała raport.

Skrypty powinny być testowalne

Jednym ze sposobów pisania kodu, który jest łatwo przetestować, jest pisanie skryptu/funkcji, która robi tylko jedną rzecz. Wracając do naszego przykładu, pozyskanie danych może być jedną czynnością wykonywaną przez nasz skrypt. Pytanie jak to zaimplementujemy.

Odpytując komputery w naszej sieci możemy spotkać się z problemem, iż odpytywany komputer nie będzie włączony, nie ma go w sieci, usługa WinRM będzie wyłączona. Co w tych przydechach ma zrobić nasz skrypt? Może dobrze by było gdyby sprawdził czy komputer jest w sieci, używając polecenia:

Test-Connection

Jeżeli komputer odpowie to znaczy, że jest dostępny i odpytuje go o potrzebne mi informacje.

Powyższe myślenie jest często spotykane i stoi w sprzeczności z pierwszą zasadą „Narzędzie robi jedną rzecz”. Tak napisany skrypt w tym momencie robi kilka czynności. Sprawdza czy komputer jest w sieci i odczytuje z niego dane. Proces testowania skryptu musiał by uwzględniać nie tylko czy nasz skrypt pozyskał dane z komputera zdalnego, ale czy komputer zdalny odpowiada na pingi czy nie. Może bowiem zaistnieć sytuacja w której komputer będzie dostępny w sieci i odpowie na pingi, jak i taka w której usługa WinRM będzie wyłączoną i pozyskanie informacji za pomocą CIM będzie niemożliwe.

Jak więc należy podejść do problemu?

Będąc świadomym tego, iż komputer może być niedostępny mogę przygotować skrypt na obsługę tego błędu. Nie próbuje zapobiec problemowi sprawdzając czy komputer jest w sieci, ale godzę się na to że mój skrypt wyrzuci błąd i zajmuję się obsługą tego błędu. Informację o komputerze z którym się nie połączyłem mogę zapisać do pliku. Dzięki takiemu podejściu moje narzędzie robi jedną rzecz i jestem wstanie przeprowadzić jej testy dla scenariusza w którym komputer zdalny odpowie jak i nie odpowie na działanie mojego narzędzia.

Dobre rady

  • Funkcja ma robić jedną rzecz
  • Używać konstrukcji czasownik-rzeczownik
  • Funkcja powinna zwracać niesformatowany obiekt
  • Funkcja powinna być łatwa do przetestowania
  • Funkcja powinna zwierać obiekt jednego typu
  • Zweryfikuj działanie skryptu w nowo otwartej konsoli