POWERSHELL - obrada pogrešaka

Tijekom izvođenja PowerShell skripti mogu se pojaviti različite vrste pogrešaka. Najčešći razlozi za tako nešto su privremena ili trajna nedostupnost resursa kojem se pokušava pristupiti (npr. isključeno je udaljeno računalo sa zahtijevanim resursima) ili nedostatak prava za izvođenje zahtijevane operacije (npr. pregled sadržaja neke mape).

 

Kao i u drugim programskim jezicima, tako i PowerShell nudi mogućnost obrade pogrešaka kako se izvođenje skripte ne bi prekinulo na neočekivanom mjestu, a samim tim dio naredbi u skripti ostao neizveden.

 

Krenimo od najjednostavnijeg mogućeg primjera - vrlo jednostavne skripte od dvije naredbe koja pokušava preuzeti datoteku s web-servera i spremiti je u lokalnu mapu na računalu. U ovom slučaju se, zbog potrebe pripreme primjera, sve događa na istom računalu, ali ne bi bilo nekakve bitne razlike ni da je riječ o “pravom” udaljenom serveru.

 

Sadržaj mape na serveru prije izvođenja skripte prikazan je na sljedećoj slici. U mapi se nalaze samo dva PDF dokumenta, a u skripti ćemo namjerno pokušati preuzeti datoteku koja ne postoji.

 

1

Slika 1.  Datoteke na web-serveru prije izvođenja skripte

 

Osnovni primjer skripte za preuzimanje datoteke sa servera u lokalnu mapu ima sljedeći oblik:

$wc = new-object System.Net.WebClient
"Preuzimanje datoteke sa servera"
$wc.DownloadFile("http://localhost/Test/Test1.pdf","c:\Tmp\Test1.pdf")

 

Budući da datoteka Test1.pdf ne postoji na serveru, tijekom izvođenja skripte dolazi do pojave pogreške i prekida izvođenja skripte.

PS C:\Test> ./example1.ps1                                                   
Preuzimanje datoteke sa servera
Exception calling "DownloadFile" with "2" argument(s): "The remote server returned an error: (404) Not Found."
At C:\Test\example1.ps1:3 char:4
+    $wc.DownloadFile("http://localhost/Test/Test1.pdf","c:\Tmp\Test1.p ...
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : WebException

 

Najjednostavniji način za “rješavanje” problema prikaza poruke o greški je ignoriranje njezinog prikaza. To se može napraviti izmjenom vrijednosti sistemske varijable $ErrorActionPreference. Njezinu podrazumijevanu vrijednost Continue treba promijeniti na vrijednost koja omogućava izvođenje skripte bez prikaza grešaka kod izvođenja. Početni primjer skripte nakon te promjene ima sljedeći oblik:

 

$ErrorActionPreference = 'silentlycontinue'
$wc = new-object System.Net.WebClient
"Preuzimanje datoteke sa servera"
$wc.DownloadFile("http://localhost/Test/Test1.pdf","c:\Tmp\Test1.pdf")

 

Kao rezultat izvođenja izmijenjenog primjera dobije se sljedeći rezultat:

Preuzimanje datoteke sa servera

 

Ni u ovom slučaju nepostojeća datoteka nije preuzeta sa servera, jedino što o tom problemu nismo dobili nikakvu poruku. Naravno, takvo rješenje “obrade” pogrešaka tijekom izvođenja skripte nije naročito pametno pa se koristi jedino u izuzetnim slučajevima. Na primjer, za pokušaj uklanjanja zaostalih verzija datoteka (resursa) od ranije, ako slučajno postoje, da bi se moglo krenuti od “nultog stanja” kod izvođenja skripte. Ako je ikako moguće, ovakvo rješenje ipak je bolje ne upotrebljavati.

 

2

Slika 2.  Primjer izvođenja osnovnog oblika skripte bez obrade pogrešaka

 

Problem pojave pogrešaka mnogo je bolje riješiti korištenjem odgovarajućom strukturom za obradu pogrešaka (Try .. Catch). Upotrebom navedene strukture može se prepoznati i vrsta pogreške te obraditi na različite načine.

 

Nakon dodavanja odgovarajuće “Try .. Catch” strukture, početni primjer skripte ima sljedeći oblik:

try {
   $wc = new-object System.Net.WebClient
   "Preuzimanje datoteke sa servera"
   $wc.DownloadFile("http://localhost/Test/Test1.pdf","c:\Tmp\Test1.pdf")
}
catch [System.Net.WebException],[System.IO.IOException] {
    "Greska kod preuzimanja datoteke sa servera."
}
catch {
    "Nepoznati problem tijekom rada skripte."
}

 

Kod izvođenja takvog primjera nastaju sijedeći rezultati:

Preuzimanje datoteke sa servera

Greska kod preuzimanja datoteke sa servera.

 

3

Slika 3.  Primjer izvođenja skripte s ugrađenom obradom pogrešaka

 

Datoteka s web-servera ni u ovom slučaju nije spremljena u lokalnu mapu, ali je ovaj put dobivena precizna poruka o tome gdje se pojavio problem tijekom izvođenja skripte.

 

Na sličan način kao u prethodnom primjeru u svim osjetljivim dijelovima skripti može se dodati obrada pogrešaka s različitim oblicima njihovog prepoznavanja i rješavanja.

 

Alternativni način za rješavanje problema pogrešaka u skriptama je korištenje naredbe Trap. Umjesto da se “Try .. Catch” struktura dodaje na svako mjesto u skripti gdje je moguća pojava pogreške, pomoću naredbe Trap mogu se na jednom mjestu nabrojiti svi mogući problemi koji se mogu pojaviti tijekom izvođenja te način njihovog rješavanja.

 

Slijedi primjer korištenja naredbom Trap u skripti. U ovom slučaju skripta sadrži i jednu funkciju pa su zato dodani komentari koji pokazuju redoslijed izvođenja naredbi u skripti/funkciji što uključuje odgovarajuću obradu pogrešaka.

 

function Get-Eth {
    Trap {Write-Output "Nepoznata greška tijekom izvođenja."}
    Trap [System.Management.Automation.CommandNotFoundException]{
        Write-Output "Greška kod izvođenja: $_"}

    Get-NetAdapters

    Write-Output "Ovo je kraj funkcije"
}

Write-Output "Početak izvođenja skripte..."
Write-Output "U tijeku je izvođenje..."
Write-Output "Dodatno izvođenje skripte..."

Get-Eth

Write-Output "Ovo je kraj cijele skripte"

 

Rezultati izvođenja prethodnog primjera prikazani su u nastavku:

 

Početak izvođenja skripte...
U tijeku je izvođenje...
Dodatno izvođenje skripte...
Greška kod izvođenja: The term 'Get-NetAdapters' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

Get-NetAdapters : The term 'Get-NetAdapters' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

At C:\Vidi\example1.ps1:52 char:5
+     Get-NetAdapters
+     ~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (Get-NetAdapters:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

Ovo je kraj funkcije
Ovo je kraj cijele skripte

 

U određenim situacijama u vlastitim skriptama može se pripremiti generiranje vlastite pogreške kako bi se na najjednostavniji način riješili potencijalni problemi. Za to se može koristiti naredba Throw, kao što je to prikazano u sljedećem primjeru.

 

Funkcija TextOutput u primjeru očekuje jedan ulazni parametar. Ako se on navede kod pozivanja funkcije, onda se njegovom vrijednosti koristi u nastavku (u ovom slučaju samo se prikaže). Međutim, ako se vrijednost ulaznog parametra ne navede, onda se izaziva pojava odgovarajuće pogreške u skripti.

 

function TextOutput([string]$text)
{
       if ($text -eq "")
       {
             Throw "Morate obavezno upisati tekst."
       }
       else
       {
             "OUTPUT: $text"
       }
}
TextOutput Zdravo
TextOutput

Rezultati izvođenja skripte prikazani su na sljedećoj slici.

 

4

Slika 4.  Primjer skripte s primjerom generiranja “vlastitih pogrešaka”

 

Nekom od tehnika opisanih u ovom tekstu mogu se pisati PowerShell skripte znatno otpornije na pogreške pa samim tim i pouzdanije u izvođenju.

Kategorija