Článek přečtěte do 13 min.

Úvod do zpracování chyb v prostředí PowerShell

Mnoho skriptů PowerShellu je navrženo tak, aby se spouštěly bez obsluhy, takže je důležité zajistit, aby mohly hladce zpracovávat chyby. Správné zpracování chyb pomáhá předcházet celé řadě problémů, od nedokončených operací a výpadků systému až po ztrátu dat. Zpracování chyb musí brát v úvahu jak chyby při ukončení, které zastavují provádění skriptu, tak chyby neukončující, které umožňují pokračovat v běhu skriptu, ale mohou ovlivnit výstup.

Jedním z nejužitečnějších mechanismů pro zpracování chyb v PowerShellu je blok Try-Catch-Finally. Blok Try obsahuje kód, který by mohl vyvolat výjimku. Pokud k tomu dojde, řízení se přenese do bloku Catch, který chybu zpracuje provedením akcí, jako je přeskočení problematického souboru nebo neplatného vstupu, a také protokolováním události. Blok Finally se vždy spustí a provede úkoly čištění, jako je zavírání souborů, uvolnění zdrojů nebo protokolování informací. Například vytvoření podrobných chybových zpráv pro Try Catch v PowerShellu vám umožní podniknout příslušné akce k vyřešení problémů.

Tento dokument poskytuje hluboký ponor do bloků Try-Catch-Finally. Během toho se také budeme věnovat některým dalším metodám zpracování chyb v PowerShellu, včetně použití parametru ErrorAction k řízení toho, jak rutiny reagují na chyby, a použití proměnné $Error k ukládání historie chyb.

Jaké jsou chyby v PowerShellu?

Chyby jsou události, které mohou ovlivnit normální průběh provádění skriptu nebo jej mohou úplně zastavit. Mezi běžné příčiny chyb patří nesprávná syntaxe, chybějící soubory, nedostatečná oprávnění nebo nedostupné zdroje. Existují dva primární typy chyb, ukončovací chyby a neukončující chyby.

Ukončovací chyby: Kritické chyby, které zastavují skript

Chyby ukončení okamžitě zastaví provádění skriptu, pokud nejsou správně zpracovány. K těmto chybám dochází, když PowerShell čelí problému, ze kterého se nemůže zotavit, jako je chyba syntaxe, volání proměnné nebo souboru, který neexistuje, nebo nedostatek dostatečných oprávnění k provedení požadované operace.

Skript níže se například pokouší získat soubor users.txt:

Get-Content C:\users.txt | Get-ADUser -Properties name | Select-Object -Property SamAccountName,name

Pokud tento soubor v zadaném umístění neexistuje nebo účet, na kterém je spuštěn skript, nemá oprávnění k přístupu k němu, skript vygeneruje chybu ukončení a zastaví činnost skriptu, jak je znázorněno zde:

Neukončující chyby: Chyby, které umožňují pokračování skriptu

Neukončující chyby v PowerShellu jsou chyby, které nezastaví provádění skriptu. Tyto chyby jsou běžně generovány rutinami, které se pokoušejí zpracovat více objektů, přičemž jedna chyba nemusí nutně zastavit celý skript.

Předpokládejme například, že spustíme skript použitý v předchozím příkladu, ale nyní soubor existuje a máme oprávnění k přístupu k němu. Nemáme však konektivitu k řadiči domény. V tomto případě se spustí první příkaz a získá obsah souboru. Další příkaz však selže a generuje neukončující chyby pro každý ze tří objektů v souboru.

Nyní předpokládejme, že připojení řadiče domény je obnoveno, ale jeden objekt v souboru má neplatné uživatelské jméno. Spuštění skriptu vygeneruje neukončující chybu uvedenou níže pro objekt, ale ostatní objekty budou skriptem zpracovány.

Kde se ukládají chyby: proměnná $Error

$Error je automatické pole, které ukládá nedávné chyby zjištěné během provádění skriptu, díky čemuž je velmi užitečné při ladění a odstraňování problémů se skripty. Nejnovější chyba je uložena v indexu [0].

Když se například následující skript pokusí načíst neexistující soubor, načte výslednou chybu z $Error a zobrazí ji s popisem:

# trying to get a file which doesn't exist, and an error is generated.
Get-Item "C:\file44.txt"
# Display a message along with the last error.
Write-Host "Oops! Something went wrong Here's the error: $($Error[0])"

Pochopení bloků Try, Catch a Finally

Dobrým způsobem, jak hladce zvládnout chyby, je implementovat bloky Try-Catch-Finally.

Zkuste Blokovat: Kde se nachází kód náchylný k chybám

Blok Try obsahuje kód, který může způsobit chybu. Například následující skript je určen k zastavení procesu Poznámkového bloku. Blok Try zastaví tento proces, pokud je aktuálně spuštěn, ale pokud neběží, spuštění přeskočí na blok Catch, čímž zabrání zhroucení skriptu.

try 
catch 

Catch Block: Zpracování chyb, když nastanou

Blok Catch se používá ke zpracování výjimek, které se vyskytují v bloku Try. V následujícím příkladu PowerShell Try Catch skript vyzve uživatele k zadání čísla, vydělí 10 tímto číslem a vytiskne výsledek. Pokud je však vstupní číslo 0, pokus o dělení bude mít za následek chybu, protože není možné dělit nulou. V takovém případě se blok Catch spustí a místo čísla vytiskne chybovou zprávu.

try 
catch 
finally 

Finally blokovat: Kód, který se vždy spustí, ať už dojde k chybě nebo ne

Blok Finally se provede vždy bez ohledu na to, zda byla vyvolána výjimka.

Například následující skript definuje pole pouze se třemi prvky, ale pokusí se vytisknout pátý prvek; tato výjimka je zpracována v bloku Catch, který vypíše chybu. Blok Finally se však také provede, takže se vytiskne další zpráva.

try 
catch [System.IndexOutOfRangeException] 
finally 

Pokročilý příklad: Použití vícenásobných záchytných bloků pro různé typy výjimek

Skript může obsahovat více bloků Catch pro zpracování různých typů výjimek, což umožňuje podrobnější zpracování chyb. Rámec .Net skutečně poskytuje bohatou sadu typů zpráv o výjimkách PowerShell Try Catch , včetně následujících:

  • System.DivideByZeroException — Vyskytuje se při pokusu o dělení libovolného čísla nulou.
  • System.FormatException — Vzniká při pokusu o převod nečíselného vstupu na číslo.
  • System.ArgumentNullException — Vyskytuje se, když jsou předané argumenty null, ale nikdy by neměly být null.
  • System.IO.IOException — Vyvolá se, když dojde k chybě I/O.

Například následující skript požádá uživatele o zadání dvou čísel, převede je na celočíselný formát, vydělí první číslo druhým a vytiskne výsledek. První blok Catch řeší možnost, že vstup uživatele nelze převést do celočíselného formátu, a druhý blok Catch řeší možnost pokusu o dělení nulou.

try 
catch [System.FormatException] 
catch [System.DivideByZeroException] 
catch 
finally 

Pokročilé techniky zpracování chyb

Chcete-li vytvořit robustnější a udržovatelnější skripty, zvažte použití následujících technik zpracování chyb v kombinaci s bloky PowerShell Try and Catch:

  • Použijte $ErrorActionPreference = „Stop", abyste zajistili, že všechny chyby budou považovány za ukončující, což usnadňuje jejich zachycení.
  • Použijte -ErrorAction Stop pro jednotlivé příkazy, abyste umožnili podrobnější ovládání bez ovlivnění celého skriptu.
  • Pro přístup k podrobnostem o chybě použijte $_.Exception.Message a $PSItem.

Chytání konkrétních výjimek

Následující skript je určen k převodu vstupu od uživatele na uživatele na celé číslo a poté ke spuštění příkazu. První blok Catch zpracovává možnost neplatného uživatelského vstupu a druhý zpracovává pokusy o provedení neplatného příkazu. Pokud dojde k některé z výjimek, skript vytiskne vlastní zprávu.

try 
catch [System.FormatException] 
catch [System.Management.Automation.CommandNotFoundException] 
catch 
finally 

Použití $_.Exception.Message a $PSItem pro přístup k podrobnostem o chybě

Chcete-li získat přístup k podrobnostem o chybě v bloku Catch, můžete použít následující proměnné:

  • $_.Exception.Message poskytuje jasnou, uživatelsky přívětivou chybovou zprávu Try Catch PowerShell, která obsahuje pouze relevantní část chyby.
  • $PSItem obsahuje úplný chybový objekt, včetně typu chyby, zdroje a trasování zásobníku.

Následující skript ilustruje rozdíl ve výstupu poskytovaném těmito proměnnými:

try 
catch 
finally 

Použití příkazů Trap

Příkaz Trap definuje kód, který se spustí, když dojde ke konkrétní chybě, bez ohledu na to, kde ve skriptu k chybě došlo. V důsledku toho poskytuje mechanismus pro zpracování chyb na vyšší (globální) úrovni než jednotlivé bloky PowerShell Try-Catch.

Následující skript používá Try-Catch v PowerShellu ke zpracování možnosti pokusu o dělení nulou. Příkaz Trap zachytí jakoukoli další chybu, která se může stát, což je v tomto případě použití rutiny Get-Item se souborem, který neexistuje.

# Global error handler using trap
trap 
function Test-TryCatch 
Write-Host "Before function call"
Test-TryCatch
Write-Host "After function call"
# Triggering another error outside try-catch to see if trap works
Write-Host "Triggering an error outside Try-Catch"
Get-Item "C:\NonExistentFile.txt" -ErrorAction Stop  # Force a terminating error
Write-Host "Script completed"

Zpracování neukončujících chyb v PowerShellu

Záchytné bloky jsou navrženy tak, aby zvládly ukončovací chyby; protože neukončující chyby nezastaví provádění skriptu, nespustí blok Catch. Neukončující chyby však můžeme převést na ukončovací chyby pomocí parametru -ErrorAction Stop. Tento parametr nutí skript, aby s neukončující chybou zacházel jako s ukončovacími chybami, což blokům Catch umožní, aby je náležitě zpracovaly.

Předpokládejme, že spustíme následující skript, ale složka, ke které se pokouší přistupovat, neexistuje. Blok Try používá -ErrorAction Stop k převodu této neukončující chyby na ukončující chybu, takže ji bude zpracovávat blok Catch.

$directoryPath = "C:\NonExistentFolder"
try  catch 

Doporučené postupy pro používání Try-Catch v PowerShellu

Chcete-li maximalizovat srozumitelnost, efektivitu a udržovatelnost kódu, pečlivě vytvořte blok zpracování chyb. Konkrétně PowerShell Try-Catch by se měl používat pouze pro skutečné výjimky. Omezením kódu v bloku Try na pouze ty operace, které by mohly vyvolat výjimku, usnadňuje identifikaci zdroje výjimek a ladění skriptu. V ostatních případech zvažte příkazy if-else nebo switch.

Mezi další klíčové osvědčené postupy patří následující:

  • Ujistěte se, že kód uvnitř bloku Try se řídí principem jediné odpovědnosti, což znamená, že každý kus kódu provádí konkrétní úkol.
  • Ke zpracování různých typů výjimek použijte samostatné bloky Catch.
  • Vždy zahrňte blok Finally, abyste vyčistili kód a uvolnili prostředky.

Následující skript ilustruje některé z těchto osvědčených postupů. Před pokusem o přístup k souboru používá příkaz if s cestou test ke kontrole, zda soubor existuje. Pokud soubor neexistuje, chyba se zobrazí pomocí příkazu else. Blok Try-Catch se používá pouze ke čtení obsahu souboru; pokud skript narazí na chybu, jako je nedostatek oprávnění, blok Catch zpracuje výjimku a zobrazí chybovou zprávu.

# Define the path to the file
$filePath = "D:\NonExistentFile.txt"
# Check if the file exists
if (Test-Path -Path $filePath)  else 

PowerShell Try-Catch a pokračování skriptu

Pomocí příkazů Pokračovat

Když skript narazí na chybu v bloku Try-Catch, výchozí chování je, že skript zpracuje výjimku v bloku Catch a zastaví provádění. Existují však scénáře, kdy chceme po zpracování chyby pokračovat v provádění, například při zpracování dávky souborů nebo testování připojení k více serverům.

Chcete-li zajistit, aby jediné selhání nezastavilo celou iteraci, použijte příkaz Continue. Například následující skript testuje připojení více serverů; příkaz Continue zajišťuje, že provádění bude pokračovat i v případě, že na jednom serveru dojde k chybě.

# List of server names (replace with actual server names or IPs)
$servers = @("lhehost9", "lhehost11", "lhehost10")
foreach ($server in $servers) 
Write-Host "Script execution completed."

Pomocí proměnné $ErrorActionPreference

Dalším způsobem, jak vynutit pokračování provádění skriptu po chybě, je použití proměnné $ErrorActionPreference . Zatímco bloky Try-Catch umožňují lokalizované zpracování chyb, $ErrorActionPreference je globální nastavení, které řídí reakci PowerShellu na neukončující chyby.

Již jsme viděli, že můžete nastavit $ErrorActionPreference na „Stop", abyste zajistili, že všechny chyby budou považovány za ukončující, a tím se usnadní jejich zachycení. Tato proměnná má však další nastavení, včetně Continue (výchozí), SilentlycontinueInquire a Ignore. Výběrem nastavení pro tuto proměnnou můžete definovat, jak jsou ve skriptu spravovány chyby.

PowerShell Finally blok: Zajištění vyčištění zdrojů

Jak bylo uvedeno dříve, blok Finally se spustí po blocích Try a Catch, bez ohledu na to, zda během provádění skriptu došlo k chybě. Často se používá pro proces čištění, jako je uzavření souborů, ukončení připojení a uvolnění prostředků.

Například následující skript otevře soubor a zapíše do něj „hello world". Pokud dojde k chybě, blok Catch vytiskne zprávu. V každém případě blok Finally zajistí, aby byl datový proud souborů uzavřen, aby se zabránilo úniku prostředků.

try 
catch 
finally 

Proměnné, které ukládají a počítají chyby

PowerShell poskytuje dvě proměnné, které jsou docela užitečné při auditování a ladění skriptů, které se setkávají s více výjimkami:

  • $Error uchovává seznam chyb, ke kterým došlo během relace.
  • $Error.count poskytuje celkový počet chyb zaznamenaných v aktuální relaci.

Pro přesné sledování může být nutné čas od času během relace vymazat seznam chyb. Použití $Error.clear() odstraní všechny uložené chyby.

Použití vnořených bloků Try-Catch ke zpracování více chyb

Následující skript obsahuje dva vnořené bloky Try-Catch pro zpracování dvou různých potenciálních chyb, při pokusu o dělení nulou a při pokusu o přístup k neexistujícímu souboru:

try 
catch 
finally 

Chybové zprávy a ladění v PowerShellu

Přístup k podrobným informacím o chybě

Když se během provádění skriptu vyskytnou chyby, nestačí vědět, že k chybě došlo; potřebujeme podrobné informace k diagnostice a odstranění problému. Jak již bylo uvedeno dříve, proměnná $Error uchovává pole chybových záznamů s nejnovější chybou $Error[0] . Mezi specifické chybové vlastnosti patří ExceptionCategoryInfoInvocationInfo a ScriptStackTrace.

Vlastnost ScriptStackTrace je neocenitelná, protože poskytuje podrobný zásobník volání, který ukazuje sekvenci volání funkcí a umístění skriptů, které vedly k chybě. Chcete-li získat přístup k těmto podrobným informacím o nejnovější chybě, použijte $Error[0].ScriptStackTrace.

Poskytování vlastních chybových zpráv

Zobrazování smysluplných a uživatelsky přívětivých chybových zpráv zlepšuje použitelnost a ladění skriptů. Vlastní zprávy mohou uživatelům poskytnout přehled o tom, co se pokazilo, a někdy jim pomohou chybu opravit, například tím, že opraví nesprávnou cestu k souboru, nesprávný název procesu nebo nedostatečná oprávnění.

Pro zobrazení vlastních zpráv můžeme použít Write-host nebo write-error v bloku Catch. Chcete-li poskytnout další podrobnosti, zahrňte zprávu $_.Exception.message.

Pokud například dojde k chybě (dělení nulou) během provádění následujícího skriptu, podrobné upozornění se vytiskne na konzoli a odešle se e-mailem správci:

$SMTPServer = "lvkex.ca.lo"
$SMTPPort = 587
$From = "aadministrator@ca.lo"
$To = "administrator@ca.lo"
$Subject = "PowerShell Script Error Alert"
try 
catch 
}

Běžné případy použití pro PowerShell Try-Catch

Hromadná aktualizace uživatelských profilů při zpracování chyb při zadávání dat

Správci často používají PowerShell k automatické aktualizaci uživatelských informací ve službě Active Directory na základě souboru csv. Protože vstupní soubor může obsahovat neplatná data, je důležité používat Try-Catch ke zpracování a protokolování chyb.

Následující skript importuje soubor csv obsahující seznam uživatelů a iteruje jej, aby aktualizoval jejich popisy v AD. Vytiskne výsledky na konzole a zaznamená všechny chyby do souboru protokolu.

# Define file paths
$CsvFile = "C:\Members (7).csv"
$LogFile = "C:\logs.txt"
# Import CSV
$Users = Import-Csv -Path $CsvFile
foreach ($User in $Users) 

Řešení problémů se serverem nebo síťovým připojením

Bloky Try-Catch jsou také užitečné pro řešení problémů se serverem a síťovým připojením. Následující skript například ukazuje, jak otestovat připojení k serveru, jednou se správným názvem a jednou s nesprávným názvem:

# Define server details
$Server = "ada1.adatum.local"
$LogFile = "C:\log.txt"
try 
catch 

Závěr

Bloky Try-Catch-Finally jsou neocenitelným nástrojem pro řešení chyb ve skriptech PowerShellu. Jejich kombinací s mechanismy, jako je parametr ErrorAction a proměnné $ErrorActionPreference a $Error, můžete vytvářet robustní skripty, které běží hladce, i když nastanou neočekávané problémy. Díky tomu můžete automatizovat úkoly s jistotou, že nebudete trpět problémy, jako je neúplný provoz, výpadky systému nebo ztráta dat.

Pro více in formací nás neváhejte kontaktovat.

Zdroj: Netwrix