about_Remote_Output — 원격 명령의 출력 다루기

about_Remote_Output — 원격 명령의 출력 다루기

원격 컴퓨터에서 명령을 실행하면 결과가 생기긴 하는데, 그 결과가 로컬에서 실행한 것과 똑같지는 않아요. 언뜻 비슷해 보여도 해석하고 형식을 맞추는 방식에서 차이가 나죠. 이 문서는 원격 컴퓨터에서 실행된 명령의 출력을 어떻게 읽고, 형식을 잡고, 화면에 보여줄지를 차근차근 설명해요.

출처: Microsoft Learn — about_Remote_Output (PowerShell 공식 문서)

본문

이 문서가 다루는 것

원격 컴퓨터에서 실행된 명령의 출력을 해석하고, 형식을 지정하고, 표시하는 방법을 다뤄요. 명령이 로컬에서 실행된 것과 출력이 비슷해 보일 수 있지만, 몇 가지 의미 있는 차이가 있으니 그 차이부터 짚어볼게요.

컴퓨터 이름 표시하기

Invoke-Command cmdlet으로 원격 컴퓨터에서 명령을 실행하면, 그 명령은 데이터를 만든 컴퓨터의 이름이 담긴 객체를 돌려줘요. 이때 원격 컴퓨터 이름은 PSComputerName 속성에 들어 있어요.

많은 명령에서 PSComputerName은 기본적으로 화면에 표시돼요. 예를 들어 아래 명령은 Get-Culture 명령을 Server01과 Server02 두 대의 원격 컴퓨터에서 실행해요. 그리고 출력에는 명령이 실행된 원격 컴퓨터의 이름이 함께 나오죠.

Invoke-Command -ScriptBlock {Get-Culture} -ComputerName Server01, Server02
LCID  Name    DisplayName                PSComputerName
----  ----    -----------                --------------
1033  en-US   English (United States)    Server01
1033  es-AR   Spanish (Argentina)        Server02

혹시 이 이름이 필요 없다면, Invoke-CommandHideComputerName 매개 변수를 쓰면 PSComputerName 속성을 숨길 수 있어요. 이 매개 변수는 한 대의 원격 컴퓨터에서만 데이터를 모을 때 쓰도록 설계된 거예요.

아래 명령은 Server01 원격 컴퓨터에서 Get-Culture를 실행하면서, HideComputerName 매개 변수로 PSComputerName 속성과 관련 속성까지 숨겨요.

$invokeCommandSplat = @{
    ScriptBlock = {Get-Culture}
    ComputerName = 'Server01'
    HideComputerName = $true
}
Invoke-Command @invokeCommandSplat
LCID             Name             DisplayName
----             ----             -----------
1033             en-US            English (United States)

반대로, PSComputerName이 기본적으로 표시되지 않는 경우에는 직접 화면에 나타나게 할 수도 있어요.

예를 들어 아래 명령들은 Format-Table cmdlet을 써서 원격 Get-Date 명령의 출력에 PSComputerName 속성을 추가해요.

$invokeCommandSplat = @{
    ScriptBlock = {Get-Date}
    ComputerName = 'Server01', 'Server02'
}
Invoke-Command @invokeCommandSplat |
    Format-Table DateTime, PSComputerName -AutoSize
DateTime                            PSComputerName
--------                            --------------
Monday, July 21, 2008 7:16:58 PM    Server01
Monday, July 21, 2008 7:16:58 PM    Server02

역직렬화된 객체 (Deserialized objects)

원격 명령이 출력을 만들면, 그 출력은 네트워크를 타고 로컬 컴퓨터로 다시 전송돼요.

그런데 살아 있는 .NET 객체는 네트워크로 보낼 수 없어요. 그래서 살아 있는 객체를 직렬화(serialize) 해서 객체와 그 속성을 XML로 표현한 형태로 바꾼 뒤, PowerShell이 그 직렬화된 객체를 네트워크로 보내는 거예요.

로컬 컴퓨터에서는 이 직렬화된 객체를 받아 역직렬화(deserialize) 합니다. 즉 직렬화된 객체를 표준 .NET 객체로 다시 변환해요.

그런데 이 역직렬화된 객체는 살아 있는 객체가 아니에요. 직렬화되는 시점의 객체를 찍어 둔 스냅샷이죠. 속성은 포함하지만 메서드는 없어요. 그래도 PowerShell 안에서 이런 객체를 쓸 수 있고 다룰 수 있어요. 파이프라인에 넘기거나, 원하는 속성을 골라 표시하거나, 형식을 지정하는 것 모두 가능해요.

대부분의 역직렬화된 객체는 Types.ps1xml이나 Format.ps1xml 파일의 항목 덕분에 자동으로 표시 형식이 잡혀요. 다만 로컬 컴퓨터에 원격 컴퓨터에서 만들어진 객체 전부의 서식 파일이 있지는 않을 수 있어요. 서식이 잡히지 않은 객체는 콘솔에서 각 객체의 모든 속성이 줄줄이 나열된 형태로 나타나요.

객체가 자동으로 서식화되지 않을 때는 Format-Table이나 Format-List 같은 형식 지정 cmdlet을 써서 원하는 속성만 골라 표시할 수 있어요. 표 대신 Out-GridView cmdlet으로 객체를 표 형태로 보여줄 수도 있고요.

로컬 컴퓨터에 없는 cmdlet을 원격 컴퓨터에서 실행하면, 그 명령이 돌려주는 객체는 해당 객체 형식의 서식 파일이 로컬에 없어서 기대한 대로 표시되지 않을 수 있어요. 이럴 땐 Get-FormatDataExport-FormatData cmdlet으로 다른 컴퓨터의 서식 데이터를 가져와서 쓰면 돼요.

한편 DirectoryInfo 객체나 GUID처럼 일부 객체 형식은 받는 순간 살아 있는 객체로 다시 변환되기도 해요. 이런 객체는 특별한 처리나 형식 지정이 필요 없어요.

결과 순서 정렬하기

cmdlet의 ComputerName 매개 변수에 적은 컴퓨터 이름의 순서가 PowerShell이 원격 컴퓨터에 연결하는 순서를 결정해요. 그런데 결과가 화면에 나타나는 순서는 각 원격 컴퓨터에서 데이터가 도착하는 순서를 따라요.

Sort-Object cmdlet을 쓰면 PSComputerName을 기준으로 결과를 정렬할 수 있어요. 객체의 다른 속성으로 정렬하면 서로 다른 컴퓨터에서 온 결과가 출력에 섞여 뒤섞일 수 있으니 참고해 두세요.

더 알아보기