Windows PowerShell소프트웨어 인벤토리 도구 개발

Don Jones

목차

정보 찾기
프로토타입 개발
컴퓨터 이름 읽기
모듈화
파이프라인 함수

이달의 Windows Power-Shell 칼럼에서는 아주 실용적인 내용을 준비했습니다. 즉, 컴퓨터 목록을 사용하여 해당 컴퓨터의 운영 체제 빌드 번호(운영 체제 버전을 확인하는 최선의 방법)와 서비스 팩 버전 번호의 인벤토리를 만드는 도구를 개발해 보겠습니다. 그리고 솔루션 자체를 그대로 제공하기보다는 필자가 이러한 스크립트를 개발할 때 사용하는 절차를 설명할 것입니다.

도구 자체도 상당히 유용하지만 이 도구를 개발하는 데 사용되는 절차는 더욱 중요합니다. 이 개발 절차를 이해하고 여러분의 작업에 활용할 수 있게 되면 Windows PowerShell을 사용하여 거의 모든 관리 문제를 해결할 수 있게 됩니다. 생선을 줄 것이 아니라 낚시하는 방법을 알려주라는 격언이 이러한 의미일 것입니다. 이제 본격적으로 시작해 보겠습니다.

정보 찾기

첫 번째로 해결할 문제는 어디에서 운영 체제와 서비스 팩 버전 번호를 찾을지 알아내는 것인데 이것이 가장 어려운 경우가 많습니다. 레지스트리를 사용하려는 생각이 들 수도 있을 것입니다. 레지스트리는 이러한 유형의 정보를 위한 해답인 경우가 많지만 다루기 까다로울 수 있기 때문에 필자는 최후의 수단으로 사용합니다.

"검색"과 "정보"라는 단어를 생각하니까 곧바로 WMI(Windows Management Instrumentation)라는 해답이 떠올랐습니다. WMI를 떠올리게 했던 다른 키워드로 "원격"이 있습니다. Windows PowerShell 버전 1부터 WMI는 원격 정보 인벤토리나 관리 작업을 수행하기 위한 유일한 옵션이었습니다.

그러나 대부분의 Windows 시스템에는 수천 개의 WMI 클래스가 있기 때문에 필요한 정보가 포함된 클래스를 찾기가 어려울 수 있습니다. 필자는 일반적으로 웹 검색 엔진을 사용하여 "wmi service pack version number"와 같은 구를 검색하는 것으로 시작합니다. 세부적인 검색 결과를 얻으려면 이 예와 같이 구를 자세하게 지정해야 합니다.

다른 검색 용어를 사용할 수 있지만 단축 형식은 사용하지 않는 것이 좋습니다. 예를 들어 "wmi sp version"을 검색하면 그리 유용한 결과를 얻을 수 없으므로 다른 용어를 고려해야 합니다. 예를 들어 여러분이 "patch"라고 생각하는 용어를 다른 사람들은 "hotfix"라고 부를 수 있으며 "quick fix engineering"이나 "qfe patch"라고 부르는 사람도 있습니다. 올바른 결과를 얻으려면 이러한 용어를 모두 시도해 보아야 할 수 있습니다.

컴퓨터 하드웨어나 핵심 Windows OS와 관련된 항목을 검색하는 경우 대부분의 관련 WMI 클래스가 "Win32_" 접두사로 시작하므로 검색 구에 "Win32"를 추가하면 도움이 됩니다. "Win32"를 현재 검색에 추가하면 분명 최상의 결과를 얻을 수 있습니다. 필자의 경우에는 제목에서 "Win32_OperatingSystem"이 포함된 몇 개의 결과를 발견했는데 이것이 WMI 클래스 이름입니다.

여기에서 중요한 트릭은 검색 결과를 클릭하지 않는 것입니다. (조금 이상하지만 중요한 부분입니다.) 필자가 원하는 것은 해당 클래스에 대한 실제 설명서 페이지이므로 알아낸 클래스 이름을 사용하여 새로 검사를 시작합니다. 이렇게 하면 일반적으로 결과의 앞부분에 msdn.microsoft.com 웹 사이트에 대한 링크를 얻을 수 있으며 이 링크를 클릭하면 클래스 설명서 페이지로 직접 연결됩니다.

그림 1에는 해당 페이지의 일부가 나와 있으며, 여기에서는 클래스가 작동하는 OS 버전을 나열하는 중요한 특정 표 위치로 페이지를 스크롤했습니다. 필자의 경우에는 어떤 기능을 사용하기 위해 열심히 작업했지만 사용 중인 Windows 버전에는 해당 기능이 없다는 것을 나중에서야 발견한 허탈한 경험이 많습니다. 그래서 먼저 이 표를 확인하는 습관을 들였습니다.

fig01.gif

그림 1 WMI 클래스에 대한 정보 조회 (더 크게 보려면 이미지를 클릭하십시오.)

페이지를 조금 위로 스크롤하면 우리의 관심 대상인 두 가지 속성 BuildNumber와 ServicePackMajorVersion을 볼 수 있습니다. ServicePackMinorVersion도 유용할 수 있지만 Microsoft에서는 2.1 서비스 팩을 아직 본 적이 없습니다. 물론 완벽을 원한다면 확인할 가치는 충분합니다.

이달의 cmdlet: Export-CliXML 및 Import-CliXML

Windows PowerShell에는 개체의 정적 스냅숏을 특별한 XML 형식으로 저장하여 그러한 개체의 정보를 영구적으로 파일에 저장하고 나중에 살펴보기 위해 메모리로 로드하는 기능이 있습니다. 간단하게 개체를 Export-CliXML로 파이핑하여 이러한 개체를 파일로 저장할 수 있습니다.

Get-Process | Export-CliXML c:\processes.xml

나중에 이러한 개체를 셸로 가져오면 다른 개체와 마찬가지로 살펴볼 수 있습니다. "실제" 개체는 아니지만 보고 옵션은 더 많이 지원합니다. 예를 들어 어떤 유지 관리 작업이 실행될 때 지정한 서버에서 오전 3:00에 모든 프로세스를 내보내도록 스크립트를 예약할 수 있습니다. 아침에 출근해서는 그러한 프로세스를 로드하고 가령 가상 메모리 소모량을 기반으로 정렬하는 등의 작업을 할 수 있습니다.

Import-CliXML c:\processes.xml | Sort VM -descending

프로토타입 개발

작업을 진행하기 전에 이러한 속성이 정말 원하던 것이었는지 확인해야 합니다. Windows PowerShell에서 이 작업을 간단하게 수행할 수 있습니다. 먼저 필자의 로컬 컴퓨터에서 이 정보를 확인합니다.

Get-WmiObject Win32_OperatingSystem | Select
BuildNumber,ServicePackMajorVersion,ServicePack­MinorVersion

부 버전이 예상대로 0임을 알 수 있으므로 이에 대해서는 신경 쓰지 않을 것입니다. 다른 정보도 예상대로이며 필자의 Windows Server 2008 컴퓨터에서 빌드 번호는 6001이고 서비스 팩 버전은 1입니다.

이제 필자가 관리자인 원격 컴퓨터에서 비슷한 테스트를 실행해 보겠습니다.

Get-WmiObject Win32_OperatingSystem –computer Server2 | 
Select BuildNumber,ServicePackMajorVersion

만약 이 테스트가 작동하지 않으면 먼저 그 이유를 알아내야 다음 단계로 진행할 수 있습니다. 문제가 있다면 연결, 방화벽 또는 사용 권한과 관련된 문제일 수 있으며 이러한 문제는 Windows PowerShell로 해결할 수 없습니다. 여기까지 모든 것이 올바르게 작동한다면 다음 단계인 파일에서 컴퓨터 이름을 가져오는 과정으로 진행할 수 있습니다.

컴퓨터 이름 읽기

컴퓨터 이름 목록이 텍스트 파일에 저장되어 있고 각 줄에 한 개의 컴퓨터 이름이 나열되어 있다면 이 정보를 가져오는 가장 쉬운 방법은 Get-Content cmdlet을 사용하는 것입니다. 컴퓨터 이름이 텍스트 파일에 저장되어 있지 않거나 한 줄당 한 항목이 아니더라도 너무 걱정하지 마십시오. 후속 칼럼에서 다양한 환경을 위한 기술을 다룰 것입니다.

각 이름은 별도의 문자열 개체로 반환되는데 편리하게도 Get-WmiObject cmdlet의 –computerName 매개 변수는 컴퓨터 이름의 컬렉션을 받으므로 이를 사용할 수 있습니다.

$names = Get-Content c:\computernames.txt
Get-WmiObject Win32_OperatingSystem –comp $names | Select
BuildNumber,ServicePackMajorVersion

이제 문제는 숫자의 목록이 출력되지만 어떤 숫자가 어떤 컴퓨터에 대한 것인지에 대한 표시가 없다는 것입니다. 다행스럽게도 Win32_OperatingSystem 클래스에는 컴퓨터 이름을 포함하는 CSName이라는 다른 속성이 있으므로 이 속성을 출력에 추가하여 깔끔한 인벤토리를 만들 수 있습니다.

$names = Get-Content c:\computernames.txt
Get-WmiObject Win32_OperatingSystem –comp $names | Select
CSName,BuildNumber,ServicePackMajorVersion

모듈화

이러한 모든 단계를 아직 경험이 부족한 개발자가 사용하기에는 다소 복잡하므로 마지막 단계는 이 모든 기능을 하나의 함수로 모듈화하는 것입니다. 파일 이름을 받고 필요한 모든 작업을 수행하는 함수를 작성하는 것이 한 가지 방법입니다.

Function Get-SPInventory ([string]$filename) {
  $names = Get-Content $filename
  Get-WmiObject Win32_OperatingSystem –comp  $names | Select   CSName,BuildNumber,ServicePackMajorVersion
}

여기에서 볼 수 있듯이 작업한 코드를 Get-SPInventory라는 함수에 래핑했습니다. $filename이라는 입력 매개 변수와 함께 정의했으므로 다음과 같이 호출할 수 있습니다.

Get-SPInventory c:\computernames.txt

이 결과는 다음과 같이 일반적인 Windows PowerShell 명령을 사용하여 CSV 파일로 파이핑이나 HTML로 변환 또는 다른 형식 지정과 같은 작업을 할 수 있습니다.

Get-SPInventory c:\computernames.txt | 
Export-CSV SPInventory.csv

그러나 아직 완벽한 것은 아닙니다. 각 컴퓨터의 BIOS 일련 번호와 같이 Win32_OperatingSystem 클래스에 포함되어 있지 않은 정보를 인벤토리에 추가하려는 경우에는 어떻게 해야 할까요? 컴퓨터의 BIOS 일련 번호를 고유 식별자로 사용하는 CMDB(Configuration Management Database)가 많으므로 이러한 기능이 있다면 유용할 것입니다.

이 밖에도 함수의 출력을 조금 더 유연하게 만들어서 결과를 정렬하거나 필터링하는 등의 작업을 수월하게 할 수 있으면 좋을 것입니다. 또한 최종 출력에 오래된 서비스 팩 버전이 있는 Windows Server 2003 컴퓨터만 포함하도록 선택하여 업데이트가 필요한 컴퓨터 목록을 만드는 기능이 있다면 좋을 것입니다.

파이프라인 함수

다음은 Windows PowerShell 파이프라인에서 제 역할을 할 수 있도록 함수를 수정할 것입니다. 구체적으로 함수가 파이프라인에서 직접 컴퓨터 이름을 받기를 원합니다. 이렇게 하면 함수를 사용할 때마다 어디에서 컴퓨터 이름을 가져올지 결정할 수 있습니다. 컴퓨터 이름은 파일이나 Active Directory에 있을 수 있으며 두 경우에 모두 같은 함수를 사용하기를 원합니다. 다음은 파이프라인에 맞게 다시 작성한 함수입니다.

Function Get-SPInventory {
  PROCESS {
    $wmi = Get-WmiObject Win32_OperatingSystem       –comp $_ | Select     CSName,BuildNumber,ServicePackMajorVersion
    Write-Output $wmi
  }
}

이 함수는 함수에 파이핑하는 각 파이프라인 개체당 한 번씩 실행되는 PROCESS 스크립트 블록을 사용하는 특수한 유형의 함수입니다. 이 칼럼을 열심히 읽은 독자라면 2008년 7월호 칼럼(technet.microsoft.com/magazine/cc644947.aspx)에서 PROCESS 스크립트 블록에 대해 설명한 것을 기억할 것입니다. 특수 $_ 변수는 자동으로 파이프라인 입력으로 채워지므로 컴퓨터 이름을 파이핑하면 아무 문제 없이 작동할 것입니다. 새로운 함수는 다음과 같이 사용할 수 있습니다.

Get-Content c:\computernames.txt | Get-SPInventory

여기에서 볼 수 있듯이 새로운 함수는 다양한 원본에서 컴퓨터 이름을 받는 유연성을 갖추고 있습니다. 명령의 Get-Content 부분을 컴퓨터 이름을 검색하는 데 필요한 다른 명령으로 대체하면 됩니다. 출력을 구성하기 전에 다른 WMI 클래스(또는 다른 데이터 원본)를 쿼리하여 더욱 견고한 출력을 생성하는 기반을 준비할 수 있습니다.

이달의 칼럼은 여기까지입니다. 다음 달에는 출력에 BIOS 일련 번호를 포함하도록 이 함수를 확장해 보겠습니다.

Don Jones는 Concentrated Technology의 설집자이며 여러 IT 서적을 집필하기도 했습니다. 주간 Windows PowerShell 팁을 보거나 문의 사항이 있으면 www.ConcentratedTech.com을 방문하십시오.