Windows PowerShell오류 트래핑

Don Jones

목차

트랩 설정
중지!
범위의 이해
Break 키워드
오류 트래핑의 가치

이전 호 칼럼에서는 Windows PowerShell을 사용하여 고급 인벤토리 도구를 만드는 방법에 대해 설명했습니다. 필자가 만든 도구는 Windows PowerShell의 기본 기능 및 함수의 개체 사용을 통해 출력과 관련된 몇 가지 옵션을 제공했습니다.

필자가 만든 함수의 약점 중 하나는 발생 가능한 오류(예: 연결 또는 권한 문제)를 매끄럽게 처리할 수 없다는 것입니다. 바로 이것이 이번 달 Windows PowerShell 칼럼에서 다룰 부분입니다. 즉, Windows PowerShell에서 제공하는 오류 처리 기능에 대해 살펴보겠습니다.

트랩 설정

Windows PowerShell의 Trap 키워드는 오류 처리기를 정의합니다. 스크립트에서 예외가 발생하면 셸은 트랩이 정의되었는지 확인합니다. 이는 예외가 발생하기 전에 스크립트에 트랩이 나와야 함을 의미합니다. 이 부분을 설명하기 위해 연결 문제가 발생하도록 테스트 스크립트를 구성하겠습니다. Get-WmiObject를 사용하여 네트워크에 존재하지 않는 컴퓨터 이름으로 연결을 시도합니다. 필자의 목표는 잘못된 컴퓨터 이름을 파일에 기록하는 오류 트랩을 만드는 것입니다. 이를 통해 잘못된 컴퓨터 이름이 담긴 파일을 얻게 됩니다. 또한 연결 가능한 두 대의 컴퓨터에 대한 연결도 포함할 것입니다(localhost를 사용). 스크립트는 그림 1에 나와 있습니다.

그림 1 트랩 추가

trap {
  write-host "Error connecting to $computer" -fore red
  "$computer" | out-file c:\demo\errors.txt -append 
  continue
}

$computer = "localhost"
get-wmiobject win32_operatingsystem -comp $computer 

$computer = "server2"
get-wmiobject win32_operatingsystem -comp $computer 

$computer = "localhost"
get-wmiobject win32_operatingsystem -comp $computer

이 스크립트의 출력은 그림 2에서 볼 수 있는데, 필자가 기대했던 것과는 다릅니다. "Error connecting to…" 메시지가 표시되지 않았고 Errors.txt 파일도 생성되지 않았습니다. 즉, 트랩이 전혀 실행되지 않은 것입니다. 어떻게 된 것일까요?

그림 2 이건 내가 원한 출력이 아니라고요!

중지!

핵심은 일반적인 셸 오류 메시지는 예외와 다르다는 점을 이해하는 것입니다. 비종료 오류와 종료 오류가 있는데 종료 오류는 파이프라인 실행을 중지하고 예외를 발생시킵니다. 오직 예외만 트랩이 가능합니다. 오류가 발생하면 셸은 기본 제공 $ErrorActionPreference 변수를 찾아 수행할 작업을 확인합니다. 이 변수의 기본값은 "Continue"입니다. 이는 "오류 메시지를 표시하고 작업을 계속 실행하라"는 의미입니다. 값을 "Stop"으로 변경하면 이 변수는 오류 메시지를 표시하고 트랩 가능한 예외를 생성합니다. 그러나 이는 스크립트의 모든 오류가 예외를 생성함을 의미합니다.

더 나은 방법은 문제가 발생할 것으로 생각되는 cmdlet에서 "Stop" 동작을 사용하도록 하는 것입니다. 이렇게 하려면 모든 cmdlet에서 지원하는 일반적인 매개 변수인 –ErrorAction(또는 –EA) 매개 변수를 사용하면 됩니다. 그림 3에는 수정한 버전의 스크립트가 나와 있습니다. 이 스크립트는 의도에 맞게 동작하여 그림 4의 출력을 생성합니다.

그림 3 -ErrorAction 사용

trap {
  write-host "Error connecting to $computer" -fore red
    "$computer" | out-file c:\demo\errors.txt -append 
  continue
}

$computer = "localhost"
get-wmiobject win32_operatingsystem -comp $computer -ea stop

$computer = "server2"
get-wmiobject win32_operatingsystem  -comp $computer -ea stop

$computer = "localhost"
get-wmiobject win32_operatingsystem  -comp $computer -ea stop

그림 4 –ErrorAction 매개 변수를 사용하여 더 유용한 결과를 얻음

트랩 마지막에 사용된 Continue는 예외를 생성한 부분 다음의 코드 줄에서 실행을 재개하도록 셸에 지시합니다. 또 다른 옵션은 Break 키워드를 사용하는 것입니다. 이에 대해서는 잠시 후에 설명하겠습니다. 스크립트에 정의된 $computer 변수가 트랩 내에서 여전히 유효하다는 점에도 주목하십시오. 이는 트랩이 스크립트 자체의 자식 범위이기 때문입니다. 즉, 트랩은 스크립트 내의 모든 변수를 볼 수 있습니다. 여기에 대해서도 잠시 후에 설명하겠습니다.

범위의 이해

Windows PowerShell의 오류 트래핑에서 특히 까다로운 부분이 범위의 사용입니다. 셸 자체는 전역 범위를 나타냅니다. 이 범위에는 셸 내에 들어가는 모든 항목이 포함됩니다. 스크립트를 실행하면 각 스크립트는 고유한 범위를 갖게 됩니다. 함수를 정의하면 함수 내부가 해당 함수의 고유한 범위가 되는 식입니다. 이로써 일종의 부모/자식 계층 구조가 생기게 됩니다.

예외가 발생하면 셸은 현재 범위 안에서 트랩을 찾습니다. 이는 함수 내의 예외는 해당 함수 내부에 있는 트랩을 찾게 된다는 것을 의미합니다. 셸은 트랩을 찾은 경우 해당 트랩을 실행합니다. 트랩이 Continue로 끝나면 셸은 예외가 발생한 부분 뒤에 나오는 코드 줄에서 실행을 재개합니다(동일한 범위를 그대로 유지). 다음은 이 부분을 설명하기 위한 의사 코드입니다.

01  Trap {
02    # Log error to a file
03    Continue
04  }
05  Get-WmiObject Win32_Service –comp "Server2" –ea "Stop"
06  Get-Process

5번 줄에서 오류가 발생하면 1번 줄의 트랩이 실행됩니다. 트랩이 Continue로 끝났으므로 6번 줄부터 실행이 재개됩니다.

이제 약간 다른 범위 예를 살펴봅시다.

01  Trap {
02    # Log error to a file
03    Continue
04  }
05   
06  Function MyFunction {
07    Get-WmiObject Win32_Service –comp "Server2" –ea "Stop"
08    Get-Process
09  }
10   
11  MyFunction
12  Write-Host "Testing!"

7번 줄에서 오류가 발생하는 경우 셸은 함수의 범위 내에서 트랩을 찾습니다. 트랩이 없으므로 셸은 함수의 범위에서 빠져나와 부모 범위에서 트랩을 찾습니다. 부모 범위에 트랩이 있으므로 1번 줄에서 실행됩니다. 이 경우 Continue는 동일한 범위에서 예외 다음에 나오는 코드 줄부터 재개되는데, 이는 8번 줄이 아닌 12번 줄입니다. 즉, 셸은 일단 함수에서 나오면 해당 함수에는 다시 들어가지 않습니다.

이제 이 동작을 다음의 예와 비교해 보십시오.

01  Function MyFunction {
02    Trap {
03      # Log error to a file
04      Continue
05    }
06    Get-WmiObject Win32_Service –comp "Server2" –ea "Stop"
07    Get-Process
08  }
09   
10  MyFunction
11  Write-Host "Testing!"

이 경우 6번 줄의 오류는 2번 줄의 트랩을 실행하며 함수 범위 내에 머무릅니다. Continue 키워드는 이 범위 내에 머무르면서 7번 줄에서 실행을 재개합니다. 바로 이 부분이 오류가 발생할 것으로 예상되는 범위 내에 트랩을 포함할 때 얻는 이점입니다. 즉, 범위 내에 머무르면서 그 안에서 실행을 재개할 수가 있습니다. 하지만 이 방법이 여러분의 시나리오에서 작동하지 않는다면 어떻게 해야 할까요?

이달의 cmdlet: Compare-Object

이 cmdlet은 구성 기준을 관리하기 위한 유용한 도구입니다. Compare-Object, 또는 별칭 Diff는 두 개의 개체 집합을 서로 비교하도록 설계되었습니다. 기본적으로 각 개체의 모든 속성을 비교하고 차이점을 출력합니다. 서버의 서비스를 정확히 여러분이 원하는 대로 구성했다고 가정해 보겠습니다. 다음을 실행하기만 하면 기준을 만들 수 있습니다.

Get-Service | Export-CliXML c:\baseline.xml

거의 모든 개체는 Export-CliXML로 전달이 가능합니다. Export-CliXML은 개체를 XML 파일로 변환합니다. 그러면 나중에 동일한 명령(예: Get-Service)을 실행하여 그 결과를 저장된 XML과 비교할 수 있습니다. 방법은 다음과 같습니다.

Compare-Object (Get-Service) (Import-CliXML 
  c:\baseline.xml) –property name

–property 매개 변수를 추가하면 전체 개체가 아닌 해당 속성만 비교합니다. 이 경우 원래의 기준과 다른 서비스 이름의 목록을 얻게 됩니다. 이를 통해 기준이 생성된 후에 추가 또는 제거된 서비스가 있는지 알 수 있습니다.

Break 키워드

필자는 앞에서 Break 키워드에 대해 언급했습니다. 그림 5에는 Break 키워드를 사용하는 방법의 예가 나와 있습니다.

그림 5 Break 키워드 사용

01  Trap {
02    # Handle the error
03    Continue
04  }
05   
06  Function MyFunction {
07    Trap {
08      # Log error to a file
09      If ($condition) {
10        Continue
11      } Else {
12        Break
13      }
14    }
15    Get-WmiObject Win32_Service –comp "Server2" –ea "Stop"
16    Get-Process
17  }
18   
19  MyFunction
20  Write-Host "Testing!"

실행 순서를 간략히 요약하면 다음과 같습니다. 19번 줄이 가장 먼저 실행되면서 6번 줄의 함수를 호출합니다. 15번 줄이 실행되고 예외를 생성합니다. 이 예외는 7번 줄에서 트랩됩니다. 그러면 트랩은 9번 줄에 와서 결정을 내려야 합니다. $condition이 True라고 가정하면 트랩은 16번 줄에서 실행을 계속합니다.

$condition이 False인 경우 트랩은 중단(Break)됩니다. 그러면 현재 범위에서 나와 원래의 예외가 부모로 전달됩니다. 셸 관점에서 보면 이는 19번 줄이 예외를 생성하고, 이 예외를 1번 줄이 트랩함을 의미합니다. Continue 키워드에 의해 셸은 20번 줄에서 실행을 계속합니다.

실제 환경에서 이러한 트랩에는 모두 오류를 처리하고 기록하는 등의 작업을 수행하기 위해 더 많은 코드가 포함됩니다. 필자는 실제 흐름을 쉽게 볼 수 있도록 이러한 기능 코드를 생략했습니다.

오류 트래핑의 가치

오류 트래핑은 어느 경우에 구현해야 할까요? 오류가 발생할 것으로 예상되는 경우, 그리고 단순한 오류 메시지 이외의 것, 예를 들어 오류를 파일로 로깅하거나 보다 도움이 되는 오류 메시지를 표시하는 등의 동작을 원하는 경우에 한합니다.

필자는 보통 복잡한 스크립트에서 오류(발생할 것으로 예상 가능한 오류)를 보다 쉽게 처리하기 위해 오류 처리를 포함합니다. 이러한 오류에는 연결 불량 또는 사용 권한 문제 등이 포함됩니다.

오류 트래핑을 이해하는 데는 확실히 노력과 시간이 필요합니다. 하지만 Windows PowerShell 내에서 복잡한 작업을 진행하면서 보다 잘 다듬어지고 전문적인 도구를 만드는 데 도움이 되므로 오류 트래핑은 투자할 가치가 있습니다.

Don JonesWindows PowerShell: TFM의 공동 저자이며 그 외 다수의 IT 관련 서적을 집필하였습니다. concentratedtech.com의 블로그를 통해 Done Jones와 만날 수 있습니다.