Windows PowerShell파이프라인 다시 살펴보기

Don Jones

Windows PowerShell이 지난 수십 년간 주로 UNIX 및 Linux 기반 운영 체제에서 사용되어 온 명령줄 인터페이스 개념에 근거한 것임에도 불구하고 많은 이들이 Windows PowerShell의 차별화되고 새로우며 흥미로운 기능에 대해 언급해 왔습니다. 하지만 Windows PowerShell에서 이전 솔루션에서 사용되는 용어를 그대로 사용함으로써

Windows PowerShell™이 지닌 진정한 유연성 및 고유성과 Windows® 환경에 대한 뛰어난 적합성이 간과되는 경우가 많습니다.

Windows PowerShell에서 가장 자주 언급되면서도 동시에 가장 잘못 인식되고 있는 기능 중 하나는 바로 파이프라인입니다. 이는 파이프라인이 1970년대 초반, 즉 지금과는 전혀 다르고 덜 강력한 기능을 나타내던 때에 정의된 용어를 그대로 사용하고 있기 때문입니다.

파이프의 유래

첫 번째로 개발된 UNIX 셸 중 하나는 매우 원시적이며 변수 없이 가장 기본적인 스크립트 언어 요소의 기능만 가지고 있었던 Thompson 셸이었습니다. Thompson 셸은 본래의 용도인 프로그램 실행에만 적합하도록 설계되었지만 그 당시 다른 셸을 개선하는 핵심 개념인 파이프를 도입했습니다. 따라서 Thompson 셸에서는 < and > 기호를 사용하여 여러 명령을 통해 입/출력을 리디렉션하도록 지시할 수 있었습니다. 즉, 사용자가 파일에 명령 출력을 리디렉션할 수 있게 된 것입니다.

이 구문은 이후에 한 명령의 출력을 파이프로 다른 명령에 입력할 수 있도록 확장되었습니다. 이를 통해 긴 명령 시퀀스를 모두 연결하여 보다 복잡한 작업을 수행할 수 있게 되었습니다. 이 셸의 버전 4에서 파이핑에 세로 줄 문자 "|"가 채택되면서 이 문자가 이후 파이프 문자로 알려지게 되었습니다. MS-DOS®의 최초 버전에서도 이러한 문자를 통해 기본 파이핑을 구현했습니다. 예를 들어 사용자는 이를 통해 type 명령의 출력을 파이프로 more 명령에 입력하여 긴 텍스트 파일을 한 번에 한 페이지가 표시되도록 할 수 있었습니다.

1975년 UNIX 버전 6이 릴리스되던 무렵 Thompson 셸은 많은 사람들 사이에서 부적절한 것으로 간주되었으나 파이프의 이러한 개념은 셸 개발자 및 사용자에게 좋게 인식되어 오늘날 사용되고 있는 여러 기술에까지 활용되고 있습니다.

텍스트 파이핑

거의 모든 셸이 가지고 있는 제한 사항은 내재된 텍스트 기반 특성입니다. UNIX 기반 운영 체제에서 이는 실제 제한이 아닌 OS 자체의 작동 방식을 나타내는 것입니다. UNIX에서 대부분의 리소스는 일종의 파일로 표시될 수 있습니다. 따라서 한 명령으로부터 다른 명령으로 텍스트를 전달하는 기능을 통해 매우 강력한 성능과 유연성을 얻을 수 있습니다.

하지만 텍스트는 관리 정보에 대해서는 매우 제한적입니다. 예를 들어 사용자에게 Windows 컴퓨터에서 실행 중인 서비스 목록을 보여 주는 경우 사용자는 거의 틀림없이 서비스 목록을 파악할 수 있을 것입니다. 첫 번째 열에 서비스 이름을 표시하고 두 번째 열에 시작 모드를 표시하면 사용자는 이러한 텍스트를 보는 즉시 머리 속에서 작업에 사용할 수 있는 의미 있는 정보로 분석하거나 변환합니다. 하지만 컴퓨터의 경우는 인간의 뇌처럼 지능적이지 못합니다. 컴퓨터에서 목록을 가지고 필요한 작업을 수행하려면 컴퓨터에 첫 번째 열은 1-20자로 구성되어 있고 두 번째 열은 22-40자로 구성되어 있음과 같은 정보를 알려 주어야만 합니다.

오랫동안 이러한 유형의 텍스트 파일 구문 분석이 관리자가 여러 명령을 모두 연결하는 데 사용할 수 있는 유일한 방법이었습니다. 사실 하나의 프로그램 또는 명령으로부터 텍스트 출력을 받아 해당 출력을 이후 작업에 사용할 수 있는 유용한 데이터로 구문 분석해야 하는 경우가 대부분이므로 문자열 조작에 있어 VBScript 및 Perl과 같은 스크립트 언어가 훨씬 뛰어납니다. 예를 들어 필자는 Dir 명령의 텍스트 출력을 받아 파일 이름 및 날짜에 대한 출력을 분석한 다음 사용하지 않는 오래된 파일을 보관 위치로 옮기는 VBScript 작업을 작성한 적이 있습니다. 문자열 구문 분석은 입력 데이터가 변형되는 예외가 거의 항상 발생하며 이러한 예외가 발생하는 경우 가능한 모든 순열을 처리하기 위해 스크립트에서 논리를 다시 실행해야 하므로 작업하기가 매우 복잡합니다.

Windows 환경에서의 관리 스크립트 또는 자동화 작업에서는 문자열 구문 분석이 그다지 유용하지 않습니다. 이는 Windows 자체에서 액세스하기 쉬운 텍스트 형식으로는 많은 정보를 저장하지 않기 때문입니다. 대신에 Active Directory®, Windows 레지스트리 및 인증서 저장소와 같은 데이터 중심 저장소를 사용합니다. 따라서 스크립트 개발자는 특정 도구를 사용하여 텍스트 출력 형식을 생성한 다음 스크립트를 사용하여 해당 텍스트를 분석한 후 이를 가지고 필요한 작업을 수행해야 합니다.

작업이 보다 쉬워진 개체

Windows 소프트웨어 개발자는 항상 작업이 보다 용이하도록 노력해 왔습니다. 초창기 Microsoft에서는 Windows의 복잡한 내부 작업을 보다 사용하기 쉬운 방식으로 나타내기 위해 COM을 특수하게 개발했습니다. 오늘날 Microsoft® .NET Framework에서는 이러한 노력의 일환으로 소프트웨어의 내부 작업을 표준화된 방식으로 나타냅니다.

일반적으로 COM 및 .NET은 모두 항목을 개체로 제공합니다. (소프트웨어 개발자는 이렇게 단순화하는 것에 이의를 제기할 수도 있지만 여기에서는 개체라는 하나의 용어를 설명하는 것만으로도 충분합니다.) 이러한 개체에는 모두 다양한 유형의 멤버가 있습니다. 지금 우리가 가장 관심을 가지고 있는 부분은 개체의 속성 및 메서드입니다. 속성은 기본적으로는 개체를 몇몇 방식으로 설명하나 개체 또는 개체의 동작을 수정하기도 합니다. 예를 들어 서비스 개체에는 서비스 이름을 포함하는 속성 및 서비스의 시작 모드를 포함하는 다른 속성이 있을 수 있습니다. 메서드는 개체가 특정 작업을 수행하도록 합니다. 서비스 개체에는 해당 서비스로 수행할 수 있는 다양한 작업을 나타내는 중지, 시작, 일시 중지, 다시 시작 등의 메서드가 있을 수 있습니다.

프로그래밍 또는 스크립트 작성 관점에서 개체 멤버는 점 표기를 사용하여 나타낼 수 있습니다. 개체는 종종 해당 개체를 실제로 조작할 수 있는 방법을 제공하는 변수로 할당됩니다. 예를 들어 서비스를 $service 변수로 할당한 경우 $service.Stop 구문을 사용하여 이 서비스를 중지할 수 있습니다. 또는 $service.Name을 표시하여 서비스의 표시 이름을 검색할 수 있습니다.

파이프 내 개체

Windows는 거대하고 복잡한 운영 체제이며 관리 데이터를 텍스트 스타일 표현으로 저장하지 않으므로 이전 셸 기술은 Windows에 적합하지 않습니다. 예를 들어 서비스와 해당 시작 모드에 대한 형식이 지정된 목록을 생성하는 SvcList.exe라는 명령줄 도구가 있다고 가정해 봅니다. 이러한 경우 수십 년이 넘게 사용되어 온 MS-DOS 셸에 근본을 둔 Windows 명령줄 셸에서 다음과 같은 작업을 실행할 것입니다.

SvcList.exe | MyScript.vbs 

이 문은 서비스 목록을 검색하고 이 목록을 VBScript 파일에 파이프로 전달합니다. 따라서 형식이 지정된 목록을 분석하고, 시작 모드가 Disabled인 모든 서비스를 출력하는 등의 필요한 작업을 수행하도록 VBScript 파일을 작성해야 합니다. 이러한 작업은 시간이 많이 소요됩니다. 결국 문제는 SvcList.exe의 출력이 다른 명령에서 쉽게 활용할 수 있는 일반적인 형식을 공유하지 않는 고유한 출력이라는 것입니다.

하지만 개체는 이러한 일반적인 형식을 제공할 수 있으며 바로 이 점이 Windows PowerShell 파이프라인이 텍스트뿐만 아니라 전체 개체에서 작동하는 이유입니다. Get-WMIObject와 같은 cmdlet을 실행하면 실제로는 개체의 그룹(프로그래머 용어로는 컬렉션)을 생성하는 것입니다. 각 개체는 이를 조작할 수 있도록 하는 속성 및 메서드와 함께 생성됩니다. 개체를 Where-Object cmdlet으로 파이프하는 경우 원하는 개체만 표시되도록 이를 필터링할 수 있습니다. Where-Object에서는 텍스트 대신 개체를 받으므로 텍스트를 구문 분석할 필요가 없습니다. 이에 대한 예는 다음과 같습니다.

Get-WMIObject Win32_Service | Where-Object {$_.StartMode -eq “Disabled” }

또한 별칭을 통해 사용할 수 있는 간단한 구문을 선호하는 경우 다음과 같이 할 수도 있습니다.

gwmi Win32_Service | where {$_.StartMode -eq “Disabled” }

재미있는 점은 Windows PowerShell은 항상 파이프라인 아래로 개체를 전달한다는 것입니다. 셸은 더 이상 개체를 전달할 곳이 없는 경우인 파이프라인 종단에 이르러서야 비로소 기본 제공 형식 설정 규칙을 사용하여 개체의 텍스트 표현을 생성합니다. 다음 예를 살펴보겠습니다.

Gwmi Win32_Service | where {$_.StartName –eq “LocalSystem” } | select Name,StartMode

이 세 가지 cmdlet 집합은 내 로컬 컴퓨터의 모든 서비스를 검색하여 LocalSystem 계정을 사용하여 로그온하지 않는 모든 서비스를 필터링한 다음 남아 있는 서비스를 Name 및 StartMode의 두 가지 속성만 출력하는 Select-Object cmdlet으로 전달합니다. 그 결과 보안 감사 등의 용도로 사용할 수 있도록 LocalSystem으로 로그온한 서비스가 간략하게 표시됩니다.

모든 cmdlet에서 공통적인 데이터 형식인 개체를 공유하므로 복잡한 문자열 구문 분석 작업을 수행하지 않고도 각각의 데이터를 공유할 수 있습니다. Windows PowerShell에 개체를 텍스트로 표시하는 고유한 기능이 포함되어 있으므로 이 파이프의 마지막 결과는 사용자가 읽을 수 있는 텍스트 출력으로 나타납니다. 그림 1에서는 생성된 출력의 예를 보여 줍니다.

그림 1 개체를 따라 전달하는 파이프로 연결된 cmdlet에 의해 생성된 텍스트 출력

그림 1** 개체를 따라 전달하는 파이프로 연결된 cmdlet에 의해 생성된 텍스트 출력 **

파이프의 흥미로운 점

Windows PowerShell에서 파이핑을 하는 것이 이토록 놀라운 이유는 Windows PowerShell의 모든 것이 사용자가 사용할 수 있는 속성 및 메서드를 모두 갖춘 개체이기 때문입니다. 텍스트 파일도 원칙적으로 보면 문자열 개체의 집합이며 파일의 각 줄은 고유하고 독립적인 문자열 개체 역할을 합니다. 예를 들어 메모장을 사용하여 C:\Computers.txt라는 텍스트 파일을 만들어 보십시오. 파일에 텍스트를 입력한 다음 Windows PowerShell에서 다음을 실행해 봅니다.

Get-Content C:\Computers.txt | Select-Object Length | Format-List

또는 입력 작업을 별로 안 좋아한다면 다음과 같이 별칭을 사용할 수도 있습니다.

gc C:\Computers.txt | select Length | fl

이 코드는 텍스트 파일에 있는 각 줄의 길이를 문자 수로 나타내는 목록을 작성합니다. Get-Content가 파일로부터 문자열 개체를 검색하고 Select-Object에서 각 Length 속성을 확인한 다음 Format-List에서 사용자가 읽을 수 있는 텍스트 출력을 만듭니다. 이것은 사용하기에 실용적인 관리 도구는 아닐지라도 텍스트 한 줄과 같이 간단한 항목조차 Windows PowerShell의 개체라는 것을 보여 줍니다.

cmdlet에서 cmdlet으로 또는 cmdlet에서 스크립트로 개체를 전달할 수 있게 되면서 놀랍도록 강력한 "one liner"를 작성할 수 있게 되었습니다. 이는 사용자가 원하는 것을 정확하게 제공하기 위하여 긴 파이프라인에 연결되어 개체 집합을 더욱 세분화하는 간단한 문자열로 이루어진 cmdlet입니다. 실제로 스크립트 또는 프로그래밍 작업 없이도 적합한 파이프라인에 연결된 Windows PowerShell cmdlet에서는 뛰어난 결과를 수행할 수 있습니다.

다음 세대 지원

미래의 Microsoft 서버 제품 또한 Windows PowerShell을 기반으로 구축될 예정이므로 이러한 기능을 계속 활용할 수 있습니다. 예를 들어 새 Exchange Server 2007 시스템을 구현하는 경우 Windows PowerShell을 사용하여 모든 사서함을 검색하고 새 메일 서버가 위치할 사무실에 없는 사서함을 모두 필터링한 다음 해당 사서함을 새 서버로 옮기는 작업을 스크립트를 작성하지 않고도 텍스트 한 줄로 모두 수행할 수 있습니다. Exchange Server 2007 팀에서는 강력한 one-liner에 대한 긴 목록을 게시했습니다. 여기에서 파이프라인의 강력한 기능과 파이프라인에서 수행할 수 있는 관리 작업을 볼 수 있습니다.

Windows PowerShell을 사용하는 데 있어 중요한 점은 이 새로운 도구가 그간 UNIX 환경에서 오랫동안 확립되어 온 원칙 및 철학을 기반으로 하면서도 Windows 관리에 있어 그 어느 것보다 적합하다는 것을 이해하는 것입니다. Windows PowerShell이 단지 Windows용으로 고안된 UNIX 셸 모조품이라는 생각을 버리십시오. Windows PowerShell에는 Windows 플랫폼의 장점을 이용하는 새로운 개념이 포함되어 있으며 Windows의 작업 수행 방식과 밀접하게 연관되어 있습니다.

Don Jones는 Windows PowerShell MVP이며 Windows PowerShell 101(ScriptingTraining.com)의 저자입니다. 문의 사항이 있으면 www.ScriptingAnswers.com으로 연락하시기 바랍니다.

© 2008 Microsoft Corporation 및 CMP Media, LLC. All rights reserved. 이 문서의 전부 또는 일부를 무단으로 복제하는 행위는 금지됩니다..