Windows PowerShell문자열 이론

Don Jones

목차

실제 사례
복잡한 일치
문자열 세계

필자는 Tech•Ed 또는 TechMentor와 같은 컨퍼런스에서 연설할 때면 Windows PowerShell과 같은 요소의 핵심 사항을 기억하는 데 도움이 되는 일반적인 규칙을 선언하는 버릇이 있습니다. 최근에는 "Windows PowerShell에서 문자열을 구문 분석하고 있다면 무엇인가 잘못하고 있는 것입니다."라고 선언했습니다.

이것은 개체 지향 셸인 Windows PowerShell™에 관한 필자의 철학에서 나온 것입니다. 만약 어떤 서비스가 시작되었는지 확인하기 위해 서비스 목록을 텍스트 파일로 수집한 다음 해당 텍스트 파일을 구문 분석하고 있다면 정말 어렵게 일하는 것입니다. 이것은 UNIX와 같은 텍스트 기반 OS에서는 유효한 방법이지만, Windows® 자체는 물론 Windows PowerShell에서는 훨씬 더 효과적으로 개체를 사용할 수 있습니다.

셸의 다양한 서식, 필터링, 내보내기 및 기타 명령을 사용하여 스크립트의 출력을 조작하려면 직접 작성한 스크립트에서도 서식 있는 텍스트가 아닌 개체를 생성해야 합니다. (2008년 7월 Windows PowerShell 칼럼에서 스크립트 출력으로서의 사용자 지정 개체 개념에 대한 자세한 내용을 볼 수 있습니다.)

플로리다주 올랜도에서 개최된 최근 TechMentor에서 필자의 학생 중 한 명이 거의 모든 규칙들, 특히 일반적인 규칙에는 예외가 있다는 사실을 일깨워 주었습니다. "IIS 로그 파일에서 무언가를 찾는 경우에는 어떻게 합니까? 이 경우에는 텍스트 구문 분석이 필요하지 않을까요?"

맞는 말입니다. 다행히 Windows PowerShell은 개체 친화적일 뿐만 아니라 텍스트 문자열을 구문 분석하는 면에 있어서도 떨어지지 않습니다. 말이 나온 김에 생각해 보면 IIS 로그 파일, 방화벽 로그 파일 및 기타 텍스트 기반 로그를 전형적인 예로 들 수 있습니다.

실제 사례

실제로 필자는 예전에 일했던 한 회사에서 일련의 방화벽 로그 파일을 구문 분석해야 했습니다. 한 직원이 부적절한 웹 사이트를 방문했다가 적발되었는데, 이에 대한 후속 조사의 일환으로 인사 부서에서 해당 직원이 방문했던 광범위한 웹 사이트 목록을 요구했습니다. 단 하루 동안의 로그 파일을 뽑아내는 것도 꽤 어려운 작업인데, HR 담당자들은 수동으로는 수행할 엄두도 나지 않는 몇 주 동안의 기록을 원했습니다.

회사의 DHCP(Dynamic Host Configuration Protocol) 서버를 확인한 결과 해당 직원의 컴퓨터는 수개월 동안 동일한 IP 주소(이 예에서는 192.168.17.54라고 가정)를 사용한 것으로 나타났습니다. 꺼지는 일이 거의 없는 데스크톱 컴퓨터였음을 감안하면 특이한 일은 아니었습니다. 또한 방화벽 로그에서 원본 IP 주소의 기록을 보관하고 있었기 때문에 Windows PowerShell을 사용하면 작업이 수월할 것이라 생각했습니다.

이 작업의 핵심은 간과하기 쉬운 Select-String 명령에 있습니다. 또한 정규식에 대한 실무적 지식도 필요합니다(Windows PowerShell 2007년 11월호 참조).

Select-String 명령은 텍스트 파일의 파일 경로, 정규식 또는 검색할 단순 문자열을 받습니다. 그런 다음 각 로그 파일에서 정규식 또는 단순 문자열에 일치하는 각 줄을 출력합니다. 필자는 우선 직원이 사용한 데스크톱 컴퓨터의 IP 주소가 포함된 모든 줄을 얻고자 했습니다. 각 로그 파일 줄에는 인사 부서에서 원하는 날짜 및 타임스탬프가 포함되어 있었습니다.

이 작업을 수행하는 명령은 다음과 같습니다.

select-string -path c:\logs\*.txt -pattern "192.168.17.54" 
-allmatches –simplematch

–simpleMatch 매개 변수는 필자가 제공한 패턴이 정규식이 아닌 단순 문자열임을 지정합니다. 그림 1은 파일로 전달할 수도 있는 출력의 일부를 보여 줍니다. 출력에는 일치 항목이 발견된 파일 이름 및 줄 번호가 모두 포함되어 있다는 점에 주목하십시오. 이는 특정 지점으로 돌아가거나 자세한 정보를 알고자 하는 경우에 상당히 유용합니다.

이달의 cmdlet: Start-Sleep

이 cmdlet은 긴 하루 일과 중에 필요한 것, 바로 잠깐의 낮잠을 제공합니다. 그런데 Start-Sleep이 주는 이 짧은 휴식은 여러분이 아니라 Windows PowerShell 스크립트를 위한 것입니다.

스크립트에서 잠깐의 중지는 흔히 필요한 요소입니다. 예를 들어 서비스를 시작하고, 이 서비스가 준비되어 실행될 때까지 몇 초간 기다린 후, 해당 서비스에 의존하는 몇 가지 다른 작업을 수행해야 한다고 가정해 보십시오. Start-Sleep은 바로 이러한 동작에 필요합니다. 예를 들어 Start-Sleep 10을 실행하면 셸이 10초 동안 일시 중지됩니다. 더욱 정밀하게 제어해야 할 경우 Start-Sleep -milli 100을 실행하면 100밀리초 동안 일시 중지됩니다. Start-Sleep은 지정한 시간 동안 스크립트, 파이프라인 및 기타 모든 요소를 포함하는 셸을 완전히 일시 중단할 수 있습니다. 이제 누군가가 Start-Nap이라는 cmdlet을 작성해서 우리에게도 낮잠 시간이 좀 생기면 좋을텐데 말이죠.

fig01.gif

그림 1 Select-String 명령의 출력(더 크게 보려면 이미지를 클릭하십시오.)

복잡한 일치

필자는 HR 담당자들이 요청한 정보를 정확히 전달했는데, HR 담당자들은 그제야 그 정보가 자신들이 원했던 것이 아님을 깨달았습니다. 필자의 보고서에는 207.68.172.246(MSN® 웹 사이트)을 비롯하여 해당 직원이 방문했던 수많은 IP 주소가 포함되어 있었으니까요. 조사 담당자의 다음 요청은 필자의 보고서를 정리하여 문제의 웹 사이트 중 하나에 속한 것으로 확인된 특정 IP 주소에 대한 방문만 뽑아내는 것이었습니다. 이 칼럼에서는 조사에 연루된 실제 IP 주소는 공개하지 않고 대신 207.68.172.246을 사용하겠습니다. MSN 웹 사이트를 부적절한 사이트로 간주하는 경우는 별로 없지만요.

이 요청은 해결하기가 약간 더 어려울 수 있습니다. 필자가 작업했던 로그 파일에서 원본 IP 주소와 대상 IP 주소는 쉼표로 구분된 상태로 서로 인접해 있었습니다. 덕분에 간단히 검색 문자열을 "192.168.17.54,207.68.172.246"으로 바꾸고 검색을 반복할 수 있었습니다.

그러나 두 개의 IP 주소 사이에 변수 데이터가 저장되는 보다 복잡한 로그 파일이라면 단순 문자열 일치는 제대로 작동하지 않습니다. 이러한 시나리오에서는 정규식을 사용해야 합니다. 정규식은 간단한 로그 형식에서도 잘 작동하므로 여기에서는 정규식에 대해 살펴보겠습니다.

정규식 내에서는 마침표가 모든 단일 문자에 대한 와일드카드입니다. 또한 하위 식(.)*을 사용하여 두 개의 IP 주소 사이에서 문자를 수에 관계없이 검색할 수 있습니다. IP 주소 자체에 쓰이는 리터럴 마침표로 이스케이프하려면 백슬래시를 사용해야 합니다.

완성된 명령은 다음과 같습니다.

select-string -path c:\logs\*.txt -pattern 
"192\.168\.17\.54(.)*207\.68\.172\.246" –allmatches

이번에는 정규식을 사용하므로 –simpleMatch 매개 변수를 제거했습니다. 결과 출력에는 문제의 직원이 사용한 컴퓨터에서 부적절한 사이트로 판명된 특정 웹 사이트에 대한 방문만 표시되었습니다. 또한 조사 담당자가 원했던 날짜 및 타임스탬프 정보도 포함되어 출력되었습니다. 그림 2는 이와 같은 명령을 실행할 경우 얻게 되는 출력의 일부분을 보여 줍니다.

fig02.gif

그림 2 특정 사이트에 대한 방문만 표시되도록 좁혀진 검색 결과(더 크게 보려면 이미지를 클릭하십시오.)

하지만 이보다 한 단계 더 나아가 Format-Table에 출력을 전달하고 Format-Table의 기능을 사용하여 계산된 열을 표시할 수 있습니다. 테이블에 로그 파일의 파일 이름과 일치가 발생한 줄 번호를 포함할 수 있고, 일치하는 줄 자체를 표시할 수도 있습니다. 한편 셸에서 빈 문자열로 정규식 일치를 대체하여 나머지 줄(이 예에서는 날짜 및 타임스탬프)만 표시되도록 할 수 있습니다. 다음은 고급 기법으로, Windows PowerShell에서 하나의 명령줄로 문자열 데이터를 조작하고 폭넓게 사용자 지정된 출력을 생성하는 방법을 더 세부적으로 보여 줍니다.

select-string -path c:\logs\*.txt -pattern 
"192\.168\.17\.54(.)*207\.68\.172\.246" -allmatches | 
ft  filename,linenumber,@{"Label"="Time";
"Expression"={$_.line.replace
($_.matches[0],"")}} –auto

7 그림 3은 최종 결과의 형태를 보여 줍니다.

fig03.gif

그림 3 서식이 적용된 Select-String 명령의 출력(더 크게 보려면 이미지를 클릭하십시오.)

문자열 세계

필자는 Windows PowerShell의 가장 큰 장점의 하나로 개체 지향적 특성을 꼽습니다. 그러나 개체를 사용할 수 없는 경우도 있습니다.

Windows PowerShell의 주 무대는 개체 지향적 환경일 것입니다. 그러나 다행히 Windows PowerShell 팀은 사용자가 속한 환경에는 서식 있는 문자열로 된 외부 데이터가 포함되는 경우가 많다는 사실을 인식하고 Select-String 명령도 넣어 두었습니다. Select-String으로 무장하고 정규식에 익숙해진다면 Windows PowerShell을 사용하여 가장 복잡한 문자열까지 구문 분석하는 한 줄짜리 코드를 작성할 수 있습니다.

Don JonesWindows PowerShell: TFM의 공동 저자이며 그 외 다수의 IT 관련 서적을 집필하였습니다. www.concentratedtech.com의 블로그를 통해 Don Jones와 만날 수 있습니다.