본문 바로가기

운영체제/윈도우

Windows Powershell - WMI by Don Jones

 

WMI 연결, from ms TECHNET, written by Don Jones

-----------------------------------------------------
Don Jones는 SAPIEN Technologies의 프로젝트 및 서비스 담당 이사이자 Windows PowerShell: TFM(SAPIEN Press)의 공동 저자입니다

-----------------------------------------------------

필자가 VBScript에서 가장 많이 의존한 기술 중 하나는 WMI(Windows Management Instrumentation)였습니다. 그런데 흥미롭게도 Windows PowerShell은 WMI에 강력하게 연결되며 이는 기술적인 이유 때문만은 아닙니다. Windows PowerShell을 설계한 Jeffrey Snover는

WMI로 작업할 때 사용하는 Windows Server® 2003 명령줄 도구인 Wmic.exe의 개발에도 큰 역할을 했습니다. Wmic.exe는 작동 방식이 비슷하다는 측면에서 Windows PowerShell™의 전신이라고 할 수 있습니다. WMIC에 대한 자세한 내용은 John Kelbley가 TechNet Magazine 2006년 9월호에 게재한 기사(microsoft.com/technet/technetmag/issues/2006/09/WMIData)를 참조하십시오.

Windows PowerShell의 WMI 지원은 이 셸의 다른 기능과 마찬가지로 일관된 개체 지향적 방식에 따라 제공됩니다. 이런 이유 때문에 WMI는 VBScript와 같은 이전 기술보다 쉽게 배우고 사용할 수 있습니다. 특히, 애드혹 환경에서는 더욱 그렇습니다.


WMI 기초

스크립팅 서적이나 기사를 읽다 보면 거의 빠짐없이 WMI가 언급됩니다. 하지만 실제로 WMI를 사용할 때는 혼동하기 쉽기 때문에 내부적인 구성 방식을 잊어버리는 경우가 많습니다. 이 구성 방식은 Windows PowerShell에서 작동하는 방식에 있어서 특히 중요합니다.

WMI는 기본적으로 Windows® 운영 체제와 기타 Windows 기반 하드웨어 및 소프트웨어 제품의 관리 정보를 나타내는 클래스로 구성된 시스템입니다. 클래스는 실제로 특정 소프트웨어나 하드웨어 구성 요소의 속성과 기능에 대한 요약 설명일 뿐입니다. 예를 들어 논리 디스크 클래스는 일련 번호, 고정된 저장 용량, 사용 가능한 용량 등이 있는 장치를 설명할 수 있습니다. 또한 Windows 서비스를 설명하는 클래스는 서비스의 이름 유무 여부, 시작 및 중지 가능 여부 및 현재 상태 등을 지정할 수 있습니다.

WMI에서 클래스는 WMI가 관리할 수 있는 모든 대상을 나타냅니다. 특정 대상에 대한 클래스가 없으면 WMI는 해당 구성 요소를 관리할 수 없습니다. 핵심 Windows WMI 클래스에 대한 문서는 msdn2.microsoft.com/aa394554.aspx에서 볼 수 있으며 인터넷 정보 서비스, SQL Server™ 등과 같은 다른 제품에서는 자체 WMI 클래스에 대한 별도의 문서를 제공합니다.

클래스는 매우 많기 때문에 WMI에서는 클래스를 네임스페이스의 계층 구조로 구성합니다. 예를 들어 핵심 Windows OS 클래스를 포함하는 네임스페이스는 root\cimv2이지만 Microsoft IIS 6.0에서는 자체 클래스를 root\MicrosoftIISv2에 저장합니다. 편의상 root\cimv2 네임스페이스가 WMI 기본 네임스페이스로 사용되며 이 설정은 Windows PowerShell에서 공유됩니다. 따라서 이를 통해 해당 코어 클래스를 쉽게 사용할 수 있습니다.

"인스턴스"는 클래스의 실질적인 실제 발생을 나타냅니다. 예를 들어 두 개의 논리 디스크가 있는 컴퓨터에는 Win32_LogicalDisk 클래스의 인스턴스가 두 개가 있습니다. 컴퓨터에서 실행 중인 서비스가 50개이면 WMI는 50개의 Win32_Service 클래스 인스턴스를 인식합니다. WMI를 사용하는 작업은 기본적으로 WMI에 하나 이상의 인스턴스를 요청한 다음 해당 인스턴스의 속성을 검사하여 필요한 관리 정보를 찾거나 해당 인스턴스의 메서드를 실행하여 서비스 시작이나 중지 등의 관리 변경을 수행하는 방식으로 수행됩니다.

WMI는 클라이언트-서버 아키텍처를 사용합니다. Windows 2000 이후에 나온 모든 버전의 Windows에서는 WMI를 기본 제공하기 때문에(이후 버전에서는 사용 가능한 클래스 수가 늘어났음) WMI 클라이언트와 WMI 서버 소프트웨어 모두를 사용할 수 있습니다. WMI를 사용할 때는 실제로 관심 있는 컴퓨터에서 실행 중인 WMI 서비스에 요청을 전송합니다. 그러면 사용자가 지정한 WMI 인스턴스를 해당 WMI 서비스가 검색한 다음 사용자가 작업할 수 있도록 반환합니다. 이 단계에서 Windows PowerShell이 개입하여 인스턴스를 요청하고 가져와서 이를 사용하여 작업하는 프로세스를 단순화합니다.


WMI 개체 가져오기

WMI 클래스 인스턴스는 넓은 의미에서 개체라고도 합니다. 이를 감안하면 Windows PowerShell에서 이러한 인스턴스를 검색하는 방법이 Get-WMIObject cmdlet라는 점을 납득할 수 있습니다. 이 cmdlet에는 사용하기 편리한 별칭인 gwmi가 있는데 이 기사의 예제 대부분에서 이 별칭을 사용합니다. 가장 간단한 형식을 예로 들자면, 검색할 WMI 클래스 이름을 지정한 다음 결과를 보기만 하면 됩니다(그림 1 참조). gwmi win32_service를 실행한 경우 여기에는 별도로 지정된 컴퓨터나 네임스페이스가 없기 때문에 Windows PowerShell은 사용자 로컬 컴퓨터의 WMI 서비스에 연결되어 root\cimv2 네임스페이스에 연결됩니다. Windows PowerShell은 지정된 클래스의 모든 인스턴스를 검색하며, 해당 인스턴스에 대해 수행할 작업을 지정하지 않았으므로 이를 텍스트 표현으로 변환합니다. 즉, Windows PowerShell이 해당 개체를 가져와서 사람이 읽을 수 있는 텍스트로 변환합니다.

그림 1 gwmi win32_service를 실행하는 경우 Windows PowerShell은 지정된 클래스의 모든 인스턴스를 사람이 읽을 수 있는 텍스트 형식으로 반환합니다.
그림 1 gwmi win32_service를 실행하는 경우 Windows PowerShell은 지정된 클래스의 모든 인스턴스를 사람이 읽을 수 있는 텍스트 형식으로 반환합니다.

특히, Windows PowerShell은 선택된 클래스 속성의 이름과 값을 읽고 표시하는 방식으로 WMI 개체를 텍스트로 변환합니다. Win32_Service 클래스의 경우에는 6개 속성 집합을 선택합니다.

실제로 Windows PowerShell은 이런 방식으로 모든 개체를 텍스트로 변환합니다. 표시를 위해 선택하는 속성은 대부분 Windows PowerShell 설치 폴더에 있는 .format.ps1xml 파일 집합에서 정의됩니다. 이러한 형식 정의 파일에는 Microsoft의 디지털 서명이 되어 있습니다. 자체 형식 지정 파일을 제공할 수도 있지만 이러한 파일은 변경하지 않는 것이 좋습니다. 이 내용에 대해서는 이후의 칼럼에서 자세히 다루겠습니다.

gwmi cmdlet를 사용하면 컴퓨터에서 사용 가능한 클래스를 찾아낼 수 있습니다. 예를 들어 gwmi –namespace "root\cimv2" –list를 실행하면 해당 네임스페이스에 있는 전체 클래스 목록을 가져올 수 있습니다. 하지만 컴퓨터에 있는 클래스는 자신의 컴퓨터를 관리하는 경우에만 유용하다는 점을 유의하십시오. 즉, 원격 컴퓨터를 관리할 때는 해당 시스템에서 사용 가능한 클래스를 찾아야 합니다. 이렇게 하려면 gwmi의 –computer 매개 변수를 사용하여 원격 컴퓨터에 연결하면 됩니다. 예를 들어 gwmi –namespace "root\cimv2" –list –computer ServerA를 사용하면 ServerA라는 원격 컴퓨터에 있는 root\cimv2 네임스페이스의 모든 클래스가 나열됩니다.


원격 WMI

Windows PowerShell 버전 1.0에서 gwmi는 원격 관리를 직접 지원하는 유일한 cmdlet입니다. 이에 대한 주된 이유는 원격 제어가 기본 WMI 아키텍처에 내장되어 있기 때문입니다. 또한 Windows PowerShell은 기존 아키텍처를 단순히 활용하기 때문에 해당 아키텍처의 보안 기능에 종속됩니다. 다음 예제를 보십시오.

C:\> gwmi -namespace “root\cimv2” -computer
mediaserver -list
Get-WmiObject : Access is denied. (Exception
from HRESULT: 0x80070005 (E_ACCESSDENIED))
At line:1 char:5
+ gwmi <<<< -namespace “root\cimv2” -computer
mediaserver -list
PS C:\>

이 인스턴스에서는 액세스 권한이 없는 원격 컴퓨터인 MediaServer로의 연결을 시도합니다. 관리자는 이 컴퓨터의 WMI 서비스를 사용할 수 있는 권한을 갖고 있어야 하지만 로컬 워크스테이션 자격 증명이 충분하지 않을 수 있습니다. 예를 들어 신뢰되지 않은 다른 도메인에 로그인되어 있거나 권한이 낮은 계정으로 로그온했을 수 있습니다. 다행히 gwmi에서는 WMI 연결에 사용할 대체 사용자 자격 증명을 지정할 수 있는 –credential 매개 변수를 지원합니다. 아래의 간단한 예제를 살펴보겠습니다.

gwmi win32_service –credential mydomain\administrator –computer mediaserver

여기서 자격 증명, 더 구체적으로 말해 사용자 이름은 도메인\사용자 이름 형식으로 지정됩니다.

암호를 입력할 수 있는 방법은 없으며 Windows PowerShell이 암호 입력 메시지를 표시하게 됩니다. 명령줄에 암호를 입력할 수 있으면 암호를 스크립트 파일에 하드 코딩하여 보안 위험을 초래할 수 있기 때문에 Windows PowerShell에서는 의도적으로 명령줄에서 암호를 입력하는 방법을 제공하지 않습니다. 하지만 PSCredential이라고 하는 일종의 자격 증명 개체를 미리 만들어 이 –credential 매개 변수를 사용할 수도 있습니다. 여기서의 핵심은 Get-Credential cmdlet입니다.

$cred = get-credential mydomain\administrator

이 코드를 실행하더라도 암호를 묻는 메시지는 여전히 나타납니다. 하지만 이 경우에는 생성되는 자격 증명 개체가 $cred 변수에 저장됩니다. $cred의 내용을 보면 이름은 보이지만 암호는 보이지 않습니다.

PS C:\> $cred

UserName
--------
mydomain\adminstrator

위 코드를 실행한 후에는 아래 코드를 사용하여 이 자격 증명 개체를 필요할 때마다 다시 사용할 수 있습니다.

gwmi win32_service –credential $cred –computer mediaserver

이렇게 하면 재사용 가능한 자격 증명 개체를 미리 정의하여 원격 컴퓨터로의 반복적인 WMI 연결을 단순화할 수 있습니다. 하지만 현재 Get-WMIObject cmdlet는 VBScript에서 지원하는 것과 동일한 방법의 인증 수준 지정은 지원하지 않는다는 점을 유의해야 합니다. 자세한 내용은 msdn2.microsoft.com/aa389290.aspx를 참조하십시오.


자체 검색

Windows PowerShell의 장점 중 하나는 모든 항목에 대해 검색이 가능하다는 점입니다. Windows PowerShell이 사용자가 쿼리한 Win32_Service 클래스에 대한 속성 집합만 선택하는 방법에 대해 앞에서 살펴봤습니다. 하지만 이 경우에도 셸은 여전히 모든 속성에 액세스할 수 있으며 이러한 속성에 대해 보여 줍니다. 이렇게 하려면 그림 2에서처럼 개체를 Get-Member cmdlet(또는 별칭인 gm)에 연결하기만 하면 됩니다.

그림 2  개체를 Get-Member cmdlet에 연결하면 액세스할 수 있는 메서드와 속성이 표시됩니다.
그림 2  개체를 Get-Member cmdlet에 연결하면 액세스할 수 있는 메서드와 속성이 표시됩니다. (Click the image for a larger view)

또한 셸은 속성 이외 사용 가능한 메서드의 목록도 나열하기 때문에 문서를 찾아보지 않아도 클래스의 역할을 알 수 있습니다. 따라서 인스턴스의 구성을 변경하고, 서비스를 일시 중지 및 중지하는 등의 작업을 수행할 수 있는 방법을 클래스 자체에서 제공합니다.

이러한 메서드를 사용하거나 다른 속성을 표시하려면 인스턴스를 변수에 넣는 것이 가장 쉬운 방법일 때가 많습니다.

$server = gwmi win32_operatingsystem
$server.reboot()

이 샘플에서는 Win32_OperatingSystem 클래스(컴퓨터당 하나의 인스턴스만 있는 클래스)의 유일한 사용 가능 인스턴스를 검색하여 $server 변수에 저장합니다. 그런 다음 $server 변수를 사용하여 인스턴스의 Reboot 메서드에 액세스함으로써 컴퓨터를 재부팅합니다. 이 샘플을 사용하실 때는 주의하시기 바랍니다.


풍부한 쿼리 언어

VBScript나 다른 기술을 통해 WMI를 사용해온 사용자는 WQL(WMI Query Language)로 작성한 쿼리를 사용하여 WMI 클래스 인스턴스를 검색하는 것에 익숙할 것입니다. 이 경우 구문이 SQL과 비슷하기 때문에 특정 클래스의 모든 인스턴스를 검색하는 대신 특정 서비스 같은 특정 인스턴스를 쉽게 검색할 수 있습니다. 다행히 gwmi에서는 다음과 같이 쿼리를 지정할 수 있습니다.

gwmi –query “select * from win32_service where name=’alerter’”

Windows PowerShell이 정식 발표되기 직전에 추가된 gwmi의 이 구문은 매우 유용하며 이 구문을 사용하면 다른 용도로 개발한 복잡한 WMI 쿼리를 아주 쉽게 마이그레이션할 수 있습니다. 또한 Windows PowerShell은 자체 속성과 메서드가 있는 풍부한 개체를 반환하기 때문에 WMI의 관리 기능을 완전히 액세스할 수 있습니다.


WMI 진행 상황

WMI는 Windows 차기 버전용으로 계속 개발되고 있으며 새로운 클래스와 기능이 추가되고 있습니다. 또한 새로운 Microsoft 제품에 계속 추가되고 있습니다. 아직 Windows PowerShell을 기반으로 개발된 Microsoft 제품 버전이 많지는 않지만 WMI 연결 기능은 Windows PowerShell의 가장 유용한 이점 중 하나입니다.

지금까지 WMI로 할 수 있는 여러 작업 중 극히 일부만 소개했습니다. 이 글을 통해 Windows PowerShell에 관심을 가지고 직접 이용하면서 어떤 기능을 사용할 수 있는지 알아보는 계기가 되었으면 좋겠습니다