Powershell 개체(Object)와 파이프라인 (pipeline)

다른 여러 Shell들과 마찬가지로 Powershell 역시 파이프라인을 지원 한다. 여기서 파이프라인이란 명령들이 이어 지면서 앞 명령의 출력이 뒤 명령의 입력이 되는 방식을 말한다.

명령 파이프라인을 사용하는 것과 사용하지 않고 출력을 직접(변수 등을 통해) 전달하는 방식은 큰 차이점이 있다.
파이프라인을 사용 할 때에는 앞의 명령이 완전히 끝날때(모든 출력이 종료될때) 까지 대기 하는 것이 아니라. 앞뒤의 명령이 하나의 명령처럼 연결되어 출력이 나올때 마다 각 항목이 다음 명령으로 전달 되어 개별적으로 동작 한다. 물론 최종 출력도 항목마다 즉시 확인 할 수 있다.

Text를 입 출력 하는 타 Shell들과 다르게 .Net Framework 기반인 Powershell은 모든 입 출력의 개체로 이루어진다. Text라 할 지라도 그것은 String 개체이다. 따라서 파이프라인으로 전달되는 항목역시 일반적인 Text가 아니라. 출력에 해당 되는 개체이다.

예를 들어 메모장(notepad)을 띄우고 메모장 Process를 찾기 위해 다음 명령을 입력 해 보자.

Get-Process -Name notepad

다음과 같이 (비슷하게) 결과가 보일 것이다.

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    107       9     3080       9120   112     0.02   4256 notepad

이것은 단순한 텍스트 출력이 아니라. 실제 메모장의 .Net Process 개체(System.Diagnostics.Process)가 반환된 것이다. 게다가 리턴 받은 개체의 Property를 get, set 하거나 Method도 자유롭게 호출 할 수 있다.

개체의 구조를 파악 하기 위해선 Get-Member 명령을 이용 할 수 있는데 다음과 같이 파이프 라인으로 전달 해 보자.

Get-Process -Name notepad | Get-Member

다음과 같은 결과를 얻을 것이다.

   TypeName: System.Diagnostics.Process

Name                       MemberType     Definition
----                       ----------     ----------
Handles                    AliasProperty  Handles = Handlecount
Name                       AliasProperty  Name = ProcessName
NPM                        AliasProperty  NPM = NonpagedSystemMemorySize
PM                         AliasProperty  PM = PagedMemorySize
VM                         AliasProperty  VM = VirtualMemorySize
WS                         AliasProperty  WS = WorkingSet
Disposed                   Event          System.EventHandler Disposed(System.Object,
ErrorDataReceived          Event          System.Diagnostics.DataReceivedEventHandler
Exited                     Event          System.EventHandler Exited(System.Object, S
OutputDataReceived         Event          System.Diagnostics.DataReceivedEventHandler
BeginErrorReadLine         Method         System.Void BeginErrorReadLine()
BeginOutputReadLine        Method         System.Void BeginOutputReadLine()
CancelErrorRead            Method         System.Void CancelErrorRead()
CancelOutputRead           Method         System.Void CancelOutputRead()
...

TypeName 항목이 System.Diagnostics.Process 이고 모든 Member들을 확인 할 수 있을 것이다. Get-Member로 전달하지 않고 출력 했을 때 항목들이 AliasProperty로 지정되 있음을 주목하자.

이 개체의 Kill() Method를 호출하여 notepad를 닫아 보자.

$NotePadProc = Get-Process -Name notepad

$NotePadProc 는 이제 notepad Process개체이다. 만약 notepad 가 하나이상 있었다면 Collection(Array) 형태로 존재 할 것이다.

Pipeline과 Foreah-Object 를 이용하여 notepad Process를 모두 닫아보자.

$NotePadProc | Foreach-Object { $_.Kill() }

$_는 Collection요소 중 하나이다. 즉 $_에 수행하면 Collection의 모든 요소에 수행 한다.

만약 notepad Process가 하나만 있었다면 다음 명령으로도 충분하다.

$NotePadProc.Kill()

위 방법 말고도 Process 를 중지 시키는 Cmdlet인 Stop-Process 를 활용 할 수 있다. 이번에도 역시 Get-Process로 Process개체를 얻고 파이프라인을 이용하여 전달 해 보자.

먼저 notepad를 여러게 실행 시키고 다음을 실행 한다.

Get-Process notepad | Stop-Process

모든 notepad들이 종료 될 것이다.

여기서 주의 할 점은 Get-Process 에서 notepad항목이 하나씩 발견 될때 마다 즉시 Stop-Process로 전달되어 처리 되고 Get-Process는 계속 다음 notepad를 찾아서 Stop-Process로 전달 한다는 것이다..

다시 notepad를 여러게 실행시키고 이번엔 Pipeline 없이 수행해 보자.

$NoteProcs = Get-Process notepad
Stop-Process $NoteProcs

에러가 발생 할 것이다. 이유는 Stop-Process 명령은 Process Id를 입력으로 받는데 $NoteProcs이 Process 가 아닌 Collection(Object[]) 이기 때문이다. 파이프 라인 상에서는 Process를 발견 할때마다 Stop-Process로 전달 되었지만 여기선 이미 Get-Process Cmdlet이 notepad Process들을 모두 찾아 Collection으로 반환한 상태이다.

이상태에서 제대로 처리 하기 위해선 다음과 같이 하나씩 Stop-Process로 전달 해 줘야 한다.

$NoteProcs = Get-Process notepad

Foreach ($proc in $NoteProcs)
{
	Stop-Process $proc.Id
}

Stop-Process $NoteProcs

혹은

$NoteProcs = Get-Process notepad
$NoteProcs | Foreach-Object { Stop-Process $_.Id }

이와 같이 파이프라인을 잘 활용하면 복잡한 Command를 간결하게 작성 할 수 있고 여러 과정이 동시에 일어 나기 때문에 상황에 따라 더 좋은 퍼포먼스를 기대 할 수도 있다. 게다가 개별적으로 즉시 처리 되기 때문에 캐쉬 하는 부분이 적어 리소스를 절약 하는 효과도 기대 할 수 있다.

답글 남기기

이메일 주소는 공개되지 않습니다.

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> 

이 사이트는 스팸을 줄이는 아키스밋을 사용합니다. 댓글이 어떻게 처리되는지 알아보십시오.