반복문을 사용할 수 있다는 점은 상당히 중요한 부분입니다. 배치 파일의 경우도, 열거할 수 있는 대상이 있고, 이를 정확하게 열거하고 제어할 수 있으려면 반복문이 당연히 필요합니다. 이를 돕는 명령어가 바로 for 문인데 간단히 다음의 예시를 살펴보기로 하겠습니다. 아래는 한데 묶여있지 않고 각각 분리된 build.xml 파일을 한꺼번에 컴파일하기 위한 목적으로 작성된 배치 파일의 예시입니다. W 은행의 전산 시스템을 자동화하기 위하여 1년전 처음 작성하였으며, 최근 C 은행의 닷넷 프레임워크 기반 프로젝트 (이 때는 msbuild를 호출하기 위함이었습니다.) 에서도 비슷한 이유로 재사용한 적이 있는 저만의 snippet입니다. :-)
@rem Java Source 컴파일 도구
@rem 작성일 - 2010년 8월 14일
@rem 작성자 - 남정현
@rem 명령줄 입력을 숨깁니다.
@echo off
@rem 화면을 초기화합니다.
@cls
@echo Java Source 컴파일 작업 시작
@echo.
@rem /d 스위치는 디렉터리 반복 시 사용합니다.
@rem 배치 파일 내에서 변수 선언을 전달하려면 이스케이프 처리를 해야 합니다.
@rem if 문은 아래 명령과 같이 여러 줄 입력이 가능합니다.
@rem ant 명령이 실패하는 경우 Jakarta Ant Build System이 PATH에 등록되어
@rem 있는 상태인지 확인해야 합니다.
@for /d %%i in (*.*) do @if exist "%%i\build.xml". (
@echo 처리 중: "%%i"
@ant -buildfile "%%i\build.xml"
@echo.
)
@echo on
위의 부분에서 굵게 표시한 부분이 배치 파일 상에서의 for 문의 사용 예시입니다. 배치 파일 안에서 for 문을 사용하기 때문에 조금 변수명에 이스케이프 처리를 위해서 % 지시자를 한번 더 사용한다는 특이 사항만 제외하면 무난한 문법구조를 나타내고 있습니다.
for 문 바로 뒤에 오는 /d 스위치는 열거할 파일 시스템 대상 객체를 디렉터리만으로 한정하는 것으로 이 스위치를 생략할 경우 파일명이 해당 경로상에 존재할 때 같이 열거됩니다. 그 다음, 변수명, 검색할 객체 이름의 패턴 (DOS 방식이므로 전형적인 와일드 카드 패턴을 따릅니다)과 수행할 명령을 do 지시자 다음에 지정합니다. 배치 파일 안이므로 당연히 여러줄의 명령을 한번에 그룹으로 묶을 수 있습니다. 만약 /d 스위치 대신 /f 스위치를 사용할 경우 파일만이 열거될 수 있습니다. 그 외에 /r 스위치를 사용하여 재귀 탐색을 할 수 있고, /l 스위치를 사용하면 우리가 일반적인 프로그래밍 언어에서 사용하는 인덱스 기반 탐색을 위한 카운트 증감 (증가 및 감소 모두 포함됩니다.)을 수행할 수도 있습니다.
@rem 아래 명령은 시작값 1 부터 종료값 5까지 1씩 더하며 반복됩니다.
@rem C 언어로 번역한다면 for (int i = 1; i <= 5; i += 1) 과 같은 의미입니다.
@for /l %%i in (1,1,5) do @echo %%i
@rem 아래 명령은 시작값 5 부터 종료값 1까지 1씩 빼면서 반복됩니다.
@rem C 언어로 번역한다면 for (int i = 5; i >= 1; i -= 1) 과 같은 의미입니다.
@for /l %%i in (5,-1,1) do @echo %%i
보너스: Unix 및 Linux Build Script에서 흔히 사용하는 Stack 기반 Directory 탐색 구현하기
일반적으로 cd 명령 - 혹은 - chdir 명령은 forward only 탐색으로 드라이브를 바꾸거나, 전혀 다른 위치로 갑자기 이동하게 되는 경우 과거로 되돌아갈 근거가 없습니다. 그리고 DOS 기반의 명령이므로 UNIX와 같은 기능은 제공하지 않을 것이라는 일반적인 선입견까지 더해지면서 이런 기능이 "없는 것"으로 분류되기도 합니다만 실제로는 이런 기능이 NT 인터프리터에 존재합니다.
다음의 명령어를 한 번씩 실행해보면 Stack 기반의 탐색이 어떤 의미를 지니는지 아실 수 있습니다.
@rem 참고로 아래에 \ 기호가 더 붙은 이유는 %systemdrive%가 C: 까지이므로 경로임을 표시하기 위해 \를 붙여 C:\로 인지시키기 위함이었습니다.
@pushd %systemdrive%\
@pushd %windir%
@pushd %programfiles%
@popd
@popd
@popd
현재 위치가 어디이든 관계없이 첫 번째 pushd 명령으로 인해서 %systemdrive%\ 경로로 이동하고 내부 스택에 주어진 경로가 Push됩니다. 두 번째 pushd 명령으로 %windir%가 그 뒤를 이어서 내부 스택에 Push되며, 마지막으로 %programfiles% 경로가 내부 스택에 Push됩니다. 여기까지는 출력 결과만으로 놓고 보았을 때 cd 명령과 차이가 없어 보입니다. 그러나 popd 명령을 사용하면 차이가 나타납니다.
popd 명령을 처음 실행하면, 가장 마지막에 내부 스택에 들어갔던 %windir%가 Pop되고 현재 디렉터리로 변경됩니다. 그리고 다시 popd 명령을 실행하면 이번엔 %systemdrive%\로 현재 디렉터리가 변경됩니다. 그리고 다시 popd 명령을 실행하면 원래 위치로 되돌아가는 것을 볼 수 있습니다.
여기서 중요한 점은, 지금 스택에 집어넣고 빼낸 디렉터리들이 원래 위치했던 디렉터리 기준으로는 제각기 독립적인 노드들이었다는 점이며, 디렉터리를 스택 구조에 넣고 관리할 수 있으므로 배치 파일에서 탐색이 자유로워질 수 있다는 이점을 확인할 수 있습니다.
문법: for /r "검색할 디렉터리" %v in (*.확장자) do find /N /I "검색할 키워드" "%~fv" >> "결과를 저장할 파일 혹은 장치"
예시: for /r "C:\Windows" %v in (*.txt) do find /n /i "Windows" "%~fv" >> "%userprofile%\result.txt"
마무리
보잘것 없어보이는 수단이지만, 때로는 PowerShell을 검토하는 것보다, VBScript를 검토하는 것보다, 그리고 우리 프로그래머 입장에서는 C++이나 C#을 검토하는 것보다 배치 파일에 기대는 것이 더 편할 수 있습니다. 파리를 잡기 위하여 패트리어트 미사일을 날리지 말고, 가까이 있고 쉽게 사용할 수 있는 도구를 여러분의 친구로 만들기를 바라며 소소하게 써내려간 시리즈를 뒤늦게나마 마무리합니다.
Windows Azure의 Web Role과 Worker Role은 가상 PC 인스턴스를 동적으로 생성하고 부팅시키는 방식을 통하여 서비스가 구현됩니다. SDK에서 소개하는것처럼 부팅이 끝나면 배포된 Role Application의 Entrypoint Class를 통하여 서비스의 초기화 작업이 이루어지고 서비스의 시작이 완료됩니다.
그렇다면, Windows Azure VM의 파일 시스템이나 여러가지 설정을 좀 더 상세하게 파악하고 다룰 수 있다면 서비스를 좀 더 풍성하게 꾸밀 수 있지 않을까요? 그런 취지에서 Windows Azure VM의 파일 시스템 구조를 살펴보는 글을 오늘 올려봅니다.
Note: 이 글은 Windows Azure OS 1.1을 기준으로 작성된 것이며, Windows Azure 내의 가상 PC 규격은 예고 없이 변동될 수 있음을 미리 알립니다.
Windows Azure VM의 Disk Partitioning 상태는 3개입니다. C/D/E 드라이브로 구분이 되어있는 상태로 파악할 수 있으며, 각 드라이브마다 역할이 있습니다. C 드라이브의 경우 서비스 구동과 제어에 필요한 핵심 리소스들이 주로 배치되어있습니다.
펼쳐두기..
Volume in drive C has no label. Volume Serial Number is 3A83-E377
Volume in drive C has no label. Volume Serial Number is 3A83-E377
Directory of c:\
04/21/2010 05:34 PM 2,147,483,648 dumpfile.dmp 04/21/2010 05:34 PM 4,294,967,296 pagefile.sys 04/22/2010 02:06 AM <DIR> System Volume Information 2 File(s) 6,442,450,944 bytes 1 Dir(s) 235,043,717,120 bytes free
D 드라이브에는 Windows Azure OS의 실제 시스템이 포함되어있습니다. Windows Azure OS의 기동에 필요한 Windows Server 2008 R2 x64가 설치되어있는 파티션입니다.
펼쳐두기..
Volume in drive D is Windows Volume Serial Number is F674-3730
Directory of d:\
02/13/2010 12:02 AM <DIR> inetpub 10/12/2009 09:27 PM 9,663 installVHDDriver.cmd 02/12/2010 03:02 AM 2,295,664 NDP35SP1-KB976126-v2-x64.exe 03/17/2010 12:00 PM 4,908 OnlineTargetPrep.cmd 04/22/2010 09:59 AM <DIR> OSdiagnostics 04/21/2010 05:31 PM <DIR> Packages 01/19/2008 10:11 AM <DIR> PerfLogs 02/16/2010 06:12 AM <DIR> Program Files 02/16/2010 06:12 AM <DIR> Program Files (x86) 03/03/2010 08:54 AM <DIR> rdsources 10/12/2009 09:27 PM 11,057 RolePrep_completed.txt 02/16/2010 05:45 AM 7,130 StageMe.cmd 02/16/2010 05:45 AM 11 StageMe.Pass1 10/12/2009 09:27 PM 14,797 TargetPrep_completed.txt 04/22/2010 02:06 AM <DIR> Users 03/03/2010 08:54 AM <DIR> Windows 7 File(s) 2,343,230 bytes 9 Dir(s) 7,884,308,480 bytes free
상당히 익숙한 모습의 디렉터리 레이아웃이 보입니다. inetpub, PerfLogs, Program Files, Program Files (x86), Users, Windows 디렉터리는 보통의 64비트 Windows OS에서 볼 수 있는 디렉터리 레이아웃과 같습니다. 좀 더 깊이 살펴보기 위하여, %windir%\microsoft.net\framework 디렉터리 아래에 어떤 버전의 프레임워크들이 설치되어있는지도 살펴보겠습니다.
펼쳐두기..
Volume in drive D is Windows Volume Serial Number is F674-3730
Directory of D:\windows\microsoft.net\framework
02/16/2010 06:30 AM <DIR> . 02/16/2010 06:30 AM <DIR> .. 04/11/2009 04:12 PM 79,696 NETFXSBS10.exe 09/18/2006 09:32 PM 41,392 netfxsbs12.hkf 01/05/2008 11:25 AM 16,896 sbscmp10.dll 01/05/2008 11:25 AM 16,896 sbscmp20_mscorwks.dll 01/05/2008 11:25 AM 16,896 sbscmp20_perfcounter.dll 01/05/2008 11:25 AM 14,352 sbs_diasymreader.dll 01/05/2008 11:25 AM 14,336 sbs_iehost.dll 01/05/2008 11:25 AM 14,360 sbs_microsoft.jscript.dll 01/05/2008 11:25 AM 14,904 sbs_microsoft.vsa.vb.codedomprocessor.dll
01/05/2008 11:25 AM 14,344 sbs_mscordbi.dll 01/05/2008 11:25 AM 14,344 sbs_mscorrc.dll 01/05/2008 11:25 AM 14,344 sbs_mscorsec.dll 01/05/2008 11:25 AM 14,384 sbs_system.configuration.install.dll 01/05/2008 11:25 AM 14,352 sbs_system.data.dll 01/05/2008 11:25 AM 14,376 sbs_system.enterpriseservices.dll 01/05/2008 11:25 AM 14,344 sbs_VsaVb7rt.dll 01/05/2008 11:25 AM 14,352 sbs_wminet_utils.dll 01/05/2008 11:25 AM 16,896 SharedReg12.dll 04/11/2009 04:19 PM <DIR> v1.0.3705 01/19/2008 10:11 AM <DIR> v1.1.4322 04/21/2010 05:33 PM <DIR> v2.0.50727 02/13/2010 12:02 AM <DIR> v3.0 04/21/2010 05:33 PM <DIR> v3.5 04/21/2010 05:33 PM <DIR> v4.0.30128 18 File(s) 361,464 bytes 8 Dir(s) 7,884,308,480 bytes free
.NET Framework 1.0, 1.1, 2.0, 3.0, 3.5, 4.0 디렉터리가 존재하는 것을 확인할 수 있습니다. 여기서 1.0과 1.1은 관리 도구에 관련된 파일만이 포함되어있습니다. (64비트 버전을 이용할 수 있는 것은 아닙니다.) 그리고 Windows Azure VM의 버전이 1.1이므로 4.0 버전은 설치되어있지 않고, 디렉터리만 만들어져있는 상태입니다. 좀 더 나아가서, Global Assembly Cache에는 어떤 어셈블리들이 설치되어있는지도 선택적으로 살펴보겠습니다.
펼쳐두기..
Volume in drive D is Windows Volume Serial Number is F674-3730
Directory of d:\windows\assembly\gac_msil
02/16/2010 05:42 AM <DIR> Microsoft.Build.Conversion.v3.5 02/16/2010 05:42 AM <DIR> Microsoft.Build.Engine 02/16/2010 05:42 AM <DIR> Microsoft.Build.Framework 01/19/2008 10:11 AM <DIR> Microsoft.Build.Tasks 02/16/2010 05:42 AM <DIR> Microsoft.Build.Tasks.v3.5 01/19/2008 10:11 AM <DIR> Microsoft.Build.Utilities 02/16/2010 05:42 AM <DIR> Microsoft.Build.Utilities.v3.5 01/19/2008 01:53 PM <DIR> Microsoft.GroupPolicy.Reporting 01/19/2008 02:02 PM <DIR> Microsoft.GroupPolicy.Reporting.Resources
01/19/2008 10:11 AM <DIR> Microsoft.JScript 01/19/2008 10:11 AM <DIR> Microsoft.ManagementConsole 01/19/2008 02:02 PM <DIR> Microsoft.ManagementConsole.Resources 02/13/2010 12:02 AM <DIR> Microsoft.PowerShell.Commands.Management 02/13/2010 12:02 AM <DIR> Microsoft.PowerShell.Commands.Management. Resources 02/13/2010 12:02 AM <DIR> Microsoft.PowerShell.Commands.Utility 02/13/2010 12:02 AM <DIR> Microsoft.PowerShell.Commands.Utility.Res ources 02/13/2010 12:02 AM <DIR> Microsoft.PowerShell.ConsoleHost 02/13/2010 12:02 AM <DIR> Microsoft.PowerShell.ConsoleHost.Resource s 02/13/2010 12:02 AM <DIR> Microsoft.PowerShell.Security 02/13/2010 12:02 AM <DIR> Microsoft.PowerShell.Security.Resources 01/19/2008 01:53 PM <DIR> Microsoft.Storage.NfsCommon 01/19/2008 02:02 PM <DIR> Microsoft.Storage.NfsCommon.Resources 01/19/2008 01:53 PM <DIR> Microsoft.Storage.SanCommon 01/19/2008 02:02 PM <DIR> Microsoft.Storage.SanCommon.Resources 01/19/2008 01:53 PM <DIR> Microsoft.Storage.SanCommon.UI 01/19/2008 02:02 PM <DIR> Microsoft.Storage.SanCommon.UI.Resources 01/19/2008 01:53 PM <DIR> Microsoft.Storage.Vds 01/19/2008 10:11 AM <DIR> Microsoft.Tpm 01/19/2008 02:02 PM <DIR> Microsoft.Tpm.Resources 02/13/2010 12:02 AM <DIR> Microsoft.Transactions.Bridge 01/19/2008 10:11 AM <DIR> Microsoft.VisualBasic 01/19/2008 10:11 AM <DIR> Microsoft.VisualBasic.Compatibility 01/19/2008 10:11 AM <DIR> Microsoft.VisualBasic.Compatibility.Data 01/19/2008 10:11 AM <DIR> Microsoft.VisualBasic.Vsa 01/19/2008 10:11 AM <DIR> Microsoft.VisualC 02/16/2010 05:42 AM <DIR> Microsoft.VisualC.STLCLR 01/19/2008 10:11 AM <DIR> Microsoft.Vsa 01/19/2008 10:11 AM <DIR> Microsoft.Vsa.Vb.CodeDOMProcessor 02/13/2010 12:02 AM <DIR> Microsoft.Web.Administration 02/13/2010 12:02 AM <DIR> Microsoft.Web.Administration.Resources 02/13/2010 12:02 AM <DIR> Microsoft.Web.Management 02/13/2010 12:02 AM <DIR> Microsoft.Web.Management.Aspnet 02/13/2010 12:02 AM <DIR> Microsoft.Web.Management.Aspnet.Resources
02/13/2010 12:02 AM <DIR> Microsoft.Web.Management.AspnetClient 02/13/2010 12:02 AM <DIR> Microsoft.Web.Management.AspnetClient.Res ources 02/13/2010 12:02 AM <DIR> Microsoft.Web.Management.Iis 02/13/2010 12:02 AM <DIR> Microsoft.Web.Management.Iis.Resources 02/13/2010 12:02 AM <DIR> Microsoft.Web.Management.IisClient 02/13/2010 12:02 AM <DIR> Microsoft.Web.Management.IisClient.Resour ces 02/13/2010 12:02 AM <DIR> Microsoft.Web.Management.Remoting 02/13/2010 12:02 AM <DIR> Microsoft.Web.Management.Remoting.Resourc es 02/13/2010 12:02 AM <DIR> Microsoft.Web.Management.Resources 02/16/2010 06:12 AM <DIR> Microsoft.Web.Management.Rewrite 02/16/2010 06:12 AM <DIR> Microsoft.Web.Management.Rewrite.Client 02/16/2010 06:12 AM <DIR> Microsoft.Web.Management.Rewrite.Client.r esources 02/16/2010 06:12 AM <DIR> Microsoft.Web.Management.Rewrite.resource s 01/19/2008 01:53 PM <DIR> Microsoft.Windows.ServerManager 01/19/2008 02:02 PM <DIR> Microsoft.Windows.ServerManager.Resources
04/22/2010 02:06 AM <DIR> Microsoft.WindowsAzure.ServiceRuntime 01/19/2008 10:11 AM <DIR> Microsoft_VsaVb 01/19/2008 10:11 AM <DIR> MiguiControls 01/19/2008 02:02 PM <DIR> MiguiControls.Resources 01/19/2008 10:11 AM <DIR> MMCEx 01/19/2008 02:02 PM <DIR> MMCEx.Resources 01/19/2008 10:11 AM <DIR> MMCFxCommon 01/19/2008 02:02 PM <DIR> MMCFxCommon.Resources 0 File(s) 0 bytes 66 Dir(s) 7,884,111,872 bytes free
펼쳐두기..
Volume in drive D is Windows Volume Serial Number is F674-3730
Directory of d:\windows\assembly\gac_msil
02/16/2010 05:42 AM <DIR> Sentinel.v3.5Client 01/19/2008 02:02 PM <DIR> ServerManagerCmd.Resources 02/13/2010 12:02 AM <DIR> ServiceModelReg 01/19/2008 01:53 PM <DIR> SetupNfsIdMap 02/13/2010 12:02 AM <DIR> SMDiagnostics 02/13/2010 12:02 AM <DIR> SMSvcHost 02/13/2010 12:02 AM <DIR> srmgui 02/13/2010 12:02 AM <DIR> srmgui.resources 02/13/2010 12:02 AM <DIR> srmreports 02/13/2010 12:02 AM <DIR> srmreports.resources 01/19/2008 01:53 PM <DIR> StorageMgmt 01/19/2008 02:02 PM <DIR> Storagemgmt.Resources 01/19/2008 10:11 AM <DIR> sysglobl 01/19/2008 10:11 AM <DIR> System 02/16/2010 05:42 AM <DIR> System.AddIn 02/16/2010 05:42 AM <DIR> System.AddIn.Contract 02/16/2010 05:42 AM <DIR> System.ComponentModel.DataAnnotations 01/19/2008 10:11 AM <DIR> System.Configuration 01/19/2008 10:11 AM <DIR> System.Configuration.Install 02/16/2010 05:42 AM <DIR> System.Core 02/16/2010 05:42 AM <DIR> System.Data.DataSetExtensions 02/16/2010 05:42 AM <DIR> System.Data.Entity 02/16/2010 05:42 AM <DIR> System.Data.Entity.Design 02/16/2010 05:42 AM <DIR> System.Data.Linq 04/21/2010 05:33 PM <DIR> System.Data.Services 04/21/2010 05:33 PM <DIR> System.Data.Services.Client 04/21/2010 05:33 PM <DIR> System.Data.Services.Design 01/19/2008 10:11 AM <DIR> System.Data.SqlXml 01/19/2008 10:11 AM <DIR> System.Deployment 01/19/2008 10:11 AM <DIR> System.Design 01/19/2008 10:11 AM <DIR> System.DirectoryServices 02/16/2010 05:42 AM <DIR> System.DirectoryServices.AccountManagemen t 01/19/2008 10:11 AM <DIR> System.DirectoryServices.Protocols 01/19/2008 10:11 AM <DIR> System.Drawing 01/19/2008 10:11 AM <DIR> System.Drawing.Design 02/13/2010 12:02 AM <DIR> System.IdentityModel 02/13/2010 12:02 AM <DIR> System.IdentityModel.Selectors 02/13/2010 12:02 AM <DIR> System.IO.Log 01/19/2008 10:11 AM <DIR> System.Management 02/13/2010 12:02 AM <DIR> System.Management.Automation 02/13/2010 12:02 AM <DIR> System.Management.Automation.Resources 02/16/2010 05:42 AM <DIR> System.Management.Instrumentation 01/19/2008 10:11 AM <DIR> System.Messaging 02/16/2010 05:42 AM <DIR> System.Net 01/19/2008 10:11 AM <DIR> System.Runtime.Remoting 02/13/2010 12:02 AM <DIR> System.Runtime.Serialization 01/19/2008 10:11 AM <DIR> System.Runtime.Serialization.Formatters.S oap 01/19/2008 10:11 AM <DIR> System.Security 02/13/2010 12:02 AM <DIR> System.ServiceModel 02/13/2010 12:02 AM <DIR> System.ServiceModel.Install 02/13/2010 12:02 AM <DIR> System.ServiceModel.WasHosting 02/16/2010 05:42 AM <DIR> System.ServiceModel.Web 01/19/2008 10:11 AM <DIR> System.ServiceProcess 02/13/2010 12:02 AM <DIR> System.Speech 02/16/2010 05:42 AM <DIR> System.Web.Abstractions 02/16/2010 05:43 AM <DIR> System.Web.DynamicData 02/16/2010 05:42 AM <DIR> System.Web.DynamicData.Design 02/16/2010 05:43 AM <DIR> System.Web.Entity 02/16/2010 05:42 AM <DIR> System.Web.Entity.Design 02/16/2010 05:43 AM <DIR> System.Web.Extensions 02/16/2010 05:42 AM <DIR> System.Web.Extensions.Design 01/19/2008 10:11 AM <DIR> System.Web.Mobile 01/19/2008 10:11 AM <DIR> System.Web.RegularExpressions 02/16/2010 05:42 AM <DIR> System.Web.Routing 01/19/2008 10:11 AM <DIR> System.Web.Services 01/19/2008 10:11 AM <DIR> System.Windows.Forms 02/16/2010 05:42 AM <DIR> System.Windows.Presentation 02/13/2010 12:02 AM <DIR> System.Workflow.Activities 02/13/2010 12:02 AM <DIR> System.Workflow.ComponentModel 02/13/2010 12:02 AM <DIR> System.Workflow.Runtime 02/16/2010 05:42 AM <DIR> System.WorkflowServices 01/19/2008 10:11 AM <DIR> System.Xml 02/16/2010 05:42 AM <DIR> System.Xml.Linq 0 File(s) 0 bytes 73 Dir(s) 7,884,111,872 bytes free
그리고, 마지막으로 E 드라이브의 구조를 살펴보겠습니다. E 드라이브는 개발자가 업로드한 Web Role이나 Worker Role이 저장되는 파티션입니다. 보통 Windows Azure 응용프로그램이 실행되면 VM 내에서의 기본 디렉터리 위치는 E:\ (E 드라이브의 루트 디렉터리)가 됩니다.
펼쳐두기..
Volume in drive E has no label. Volume Serial Number is 5447-4618
Directory of E:\
04/22/2010 02:05 AM 0 244e457eeae84f5cb30862f26fec3b7c.0.cssx.t ag 04/22/2010 02:29 AM 9,954 7894b527-88ba-42f2-be12-eedc4e224778.csma n 04/22/2010 02:05 AM <DIR> approot 04/22/2010 02:05 AM <DIR> base 01/31/2010 10:04 AM 18,015 Cloud.uar.csman 04/22/2010 02:05 AM <DIR> diagnostics 04/21/2010 05:28 PM 532 RuntimeSetup.Manifest 04/22/2010 02:05 AM <DIR> storage 04/22/2010 02:29 AM 944 [Content_Types].xml 04/22/2010 02:05 AM <DIR> _rels 04/21/2010 05:28 PM 16 __entrypoint.txt 6 File(s) 29,461 bytes 5 Dir(s) 1,034,371,072 bytes free
위의 항목들 중에서 approot 디렉터리에는 우리가 개발한 Web Role이나 Worker Role 프로젝트 파일들의 사본이 배포됩니다. 그리고 Windows Azure VM 내에서는 __entrypoint.txt 파일에 서술된 DLL 파일을 찾아 해당 항목을 Loading하는 것으로 이해할 수 있겠습니다.
펼쳐두기..
Volume in drive E has no label. Volume Serial Number is 5447-4618
Directory of e:\approot
04/22/2010 02:05 AM <DIR> . 04/22/2010 02:05 AM <DIR> .. 04/22/2010 02:05 AM <DIR> bin 04/21/2010 05:22 PM 110 CommandDelegate.asmx 04/18/2010 11:37 AM 446 Default.aspx 04/22/2010 02:05 AM <DIR> Scripts 04/21/2010 05:28 PM 8,075 Web.config 3 File(s) 8,631 bytes 4 Dir(s) 1,034,371,072 bytes free
그 외에 base에는 Windows Azure 구동에 관한 핵심 DLL들이, storage에는 Windows Azure Drive 관련 API를 제공하는 DLL들이, diagnostics에는 진단 도구 및 ETW 관련 API들이 포함된 DLL 및 응용프로그램들이 포함되어있습니다.
그 외에, Windows Azure의 상세한 디스크 정보를 파악하기 위하여 diskpart 같은 명령어를 테스트해보기도 하였지만 COM 관련 기능의 부재로 아래와 같은 오류 메시지가 나타나는 것도 확인하였습니다.
펼쳐두기..
Microsoft DiskPart version 6.0.6002 Copyright (C) 1999-2007 Microsoft Corporation. On computer: RD00155D3127B6
DiskPart encountered an error starting the COM services.
Windows Azure OS의 내부 빌드는 ver 명령을 통하여 확인할 수 있었습니다.
Microsoft Windows [Version 6.0.6002]
whoami를 이용하여 현재 Role을 실행하는 사용자의 이름도 확인할 수 있었습니다.
cis\ab279a57-70bb-4dd5-a4ba-fe7f60abfca2
그리고, Standard User Account로 실행 중이기 때문에, netstat -nab 같은 명령어나 fsutil 같은 명령어는 각각 아래와 같은 권한 상승 필요 메시지가 나타남을 확인할 수 있었습니다.
펼쳐두기..
The FSUTIL utility requires that you have administrative privileges.
The requested operation requires elevation.
대신, netstat 명령만을 실행하였을 때는 아래와 같이 간단한 네트워크 현황을 볼 수 있습니다.
프로그램 작성에 좋은 지침이 되는 환경 변수들 몇 가지를 살펴보면, SystemDrive, RdRoleRoot, RoleRoot, PATH 같은 환경 변수들이 있겠습니다. 그리고 USERDOMAIN, COMPUTERNAME, COMSPEC 및 프로세서 관련 환경 변수들도 시스템을 분석하는데에는 역시 도움이 되는 정보들이 되겠습니다.
Windows Azure OS 내의 파일 시스템 구성은 오늘 소개한 내용이 대략적인 내용이 될 것 같습니다. Windows Azure OS의 파일 시스템과 설정을 좀 더 상세히 살펴볼 수 방법은 앞으로도 지속적으로 업데이트하겠습니다. 긴 글 읽어주셔서 감사합니다. :-)
최근 진행 중인 한국씨티은행 내 프로젝트에서 개인적으로 Visual Studio의 기본 기능들에 대해 많은 것을 다시 보게 되었습니다. 그 중에서도, 가장 뜻깊은 발견을 하나 한 것이 있는데, 환경 변수에 관한 내용이었습니다.
Visual Studio의 빌드 후 이벤트에서는 DOS 명령어를 사용하여 빌드 전이나 빌드 후의 이벤트를 사용자 정의하는 것이 가능하여 Visual Studio가 기본으로 제공하지 않는 기능들 (예: Sandcastle을 통한 코드 문서화)을 한 번에 완성할 수 있도록 할 수 있습니다. 더 나아가서는, 프로젝트 자체에 별다른 컴파일 대상 없이 빌드 순서에 따라 빌드 전 / 빌드 후 이벤트에 대한 스크립트만을 포함하는 프로젝트도 구성할 수 있을 것입니다.
그러나, 빌드 전 / 빌드 후 이벤트에는 한 가지 크게 아쉬움이 남는 부분이 있는데, 바로 명령줄 인터프리터의 환경 변수를 사용하는데 제약이 있다는 점입니다. (예를 들어 %WINDIR% 같은 변수가 되겠습니다.) 프로세스 수준, 로컬 사용자 수준, 시스템 수준 등 환경 변수로 사용할 수 있는 내용들이 많음에도 불구하고 이런 혜택을 누리지 못한다는 것은 많이 아쉬운 부분이었고, 제가 진행중인 프로젝트에 있어서는 곤란한 부분이었습니다. 그러던 중, 좋은 방법을 하나 찾게 되어 소개합니다.
빌드 후 이벤트 기능을 확장하려는 프로젝트에 대해서, 솔루션 탐색기에 해당 프로젝트에 일반 텍스트 파일을 하나 추가합니다. 그리고, 여기에 명령줄 인터프리터의 명령을 작성하고 저장한 뒤, 파일의 이름에서 확장자 부분을 .txt 대신 .cmd로 변경합니다.
변경 후에는 해당 항목의 속성으로 이동하여, "Copy to Output Directory" (한국어 명칭의 경우 출력 디렉터리로 복사) 항목을 True로 설정하여 빌드 도중에 명령줄 인터프리터 스크립트 파일이 빌드 대상 디렉터리에 복사될 수 있도록 합니다.
마지막으로, 프로젝트 속성에서, 빌드 후 이벤트 스크립트에 다음과 같이 지정하면, Visual Studio가 아닌 Windows의 명령줄 인터프리터 기준으로 수행되는 빌드 후 이벤트 처리 시스템을 완성할 수 있습니다.
$(TargetDir)은 MSBUILD에서 제공하는 환경 변수로, '\' (Back Slash) 기호가 값 내에 가장 끝에 붙어있어서 경로 구분 기호 없이 이어서 파일의 이름을 서술한다는 점을 유의하여, call 명령을 우리가 만든 CMD 파일을 가리키도록 호출한 것입니다.
만약 MSBUILD의 환경 변수를 CMD 파일 내에서 사용하기를 원할 경우, set 명령을 사용하여 변수를 공유하거나, 매개 변수를 전달하면 CMD 파일 내에서는 %0 ~ %9 까지의 예약 변수를 사용하여 MSBUILD의 환경 변수 값을 수신할 수 있습니다.
요즈음 빌드 자동화 기능을 제공하는 프레임워크와 도구들이 굉장히 많이 늘었습니다. 각기 다양한 특색이 있고 장점이 존재하지만 가끔 이와 같은 도구들의 힘을 빌리지 않고 이와 유사한 기능을 작성할 필요가 있는 경우가 있습니다. 이럴 때 한치의 손색이 없는 도구가 하나 있는데 그것이 바로 명령줄 인터프리터가 직접 처리하는 Batch File입니다. 생각보다 Batch File의 능력은 다양합니다. :-)
Note: 이 Article은 Windows XP 이상의 운영 체제에 내장되어있는 Command Interpreter에 대하여 서술한 것으로 Windows 2000, Windows 9x (Microsoft DOS 7.x), Microsoft DOS 6.x 이하에는 맞지 않는 내용도 포함되어있습니다. 착오 없으시기 바랍니다. 더불어, 다른 DOS (예: 4DOS, DR-DOS 등)에서 자체적으로 제공하는 내장 Command Interpreter의 경우 자체 내장되어있는 도움말을 참고하여야 할 수 있습니다.
문자열과 숫자의 비교
일부러 찾아보고 활용해보지 않았을 뿐이지 배치 파일에도 if와 else 구문을 그대로 사용할 수 있습니다. 물론 진짜 제대로된 프로그래밍 언어에서처럼 완벽한 논리 연산을 구현한 것은 아닙니다만 배치 파일을 사용하려는 목적에는 알맞을 수 있는 기능들을 빠짐없이 훌륭하게 구현하고 있습니다.
간단한 if / else 명령문 하나를 입력해 보겠습니다.
if test equ test (echo same string) else (echo different string)
if test neq Test (echo different string) else (echo same string)
위의 명령문을 실행하면 same string 이라는 문자열이 나타납니다. 여기서 test는 보통의 DOS 명령에서 요구하는 파일 경로에 대한 것이 아니라 순수한 문자열이나 숫자가 됩니다. 그리고 equ가 동일성 여부를 판정하는 연산자가 됩니다. 만약 같지 않음을 비교하려면 neq 연산자를 대신 사용하시면 됩니다. 나머지는 보시는 그대로 괄호로 명령문이 묶인 것을 볼 수 있습니다. 괄호를 입력하지 않으면 참 조건시 실행될 echo 문의 나머지 뒷쪽 부분들이 전부 echo 명령에 대한 매개 변수로 지정되기 때문에 이를 구분한 것입니다. 그러면 이번엔 아래와 같이 특정 문자를 대문자로 바꿔서 명령을 수행해보도록 하겠습니다.
if Test equ test (echo same string) else (echo different string)
위의 명령문을 실행하면 기대한 대로 different string 이라는 문자열이 나타납니다. 여기에 부수적으로, 대/소문자 구분을 무시하여 비교하는 명령을 수행해보기로 하겠습니다.
if /i Test equ test (echo same string) else (echo different string)
/i 스위치가 대/소문자 구분을 무시하도록 지정한 것으로 결과는 기대한 대로 same string 이라는 문자열이 될 것입니다. 그렇다면 이 결과에 부정 연산자를 취하여 결과를 뒤집는 것도 가능할까요? 방법은 간단합니다.
if /i not Test equ test (echo same string) else (echo different string)
/i 스위치가 없다면 if 문 바로 다음 앞에, /i 스위치가 있다면 /i 스위치 바로 다음 앞에 not 연산자를 지정하여 Test equ test 식에 대한 결과를 반전 연산자를 통하여 뒤집게 되므로 기대하였던대로 different string 이라는 문자열이 대신 출력될 것입니다.
그렇다면 같음을 비교하는 것 말고 문자열과 숫자의 크고 작음을 비교하는 것도 가능할까요? 이번엔 아래와 같이 명령어를 넣어보겠습니다.
if test lss tess (echo a) else (echo b)
if test lss test (echo a) else (echo b)
if test lss tesu (echo a) else (echo b)
위의 명령들에 대한 수행 결과는 각각 b, b, a 가 됩니다. 프로그래밍 코드 식으로 풀이해보면 compare("test", x) < 0 에 비유할 수 있으며 앞서 본 tess와 test는 test보다 앞서거나 동일하므로 else 절의 문장이 수행된 것입니다. 반면 tesu는 test보다 뒤에 오는 단어이므로 if 절의 문장이 수행된 것입니다.
만약 위의 예제에서 lss 대신 leq를 선택한다면 test와 test를 비교하는 부분에서 b 대신 a가 선택 될 것입니다. 프로그래밍 코드 식으로 풀이한다면 compare("test", "test") <= 0 가 되므로 참에 해당되기 때문입니다. 더불어, 위의 연산 식 역시 /i 스위치와 not 연산자의 적용을 그대로 유지할 수 있으므로 이들 옵션이 위의 식에 대하여 끼치는 영향은 동일합니다.
프로그래밍 코드 식으로 compare("test", x) > 0 연산에 해당되는 것은 gtr 연산자이며, compare("test", x) >= 0 연산에 해당되는 것은 geq 연산자가 될 것입니다.
지금 이야기한 기능들은 단독으로 사용될 때 보다는 배치 파일에 주어지는 매개 변수들이나 미리 설정된 환경 변수들의 값을 다루는 데에 더 요긴하게 사용됩니다.
다음 Chapter에서는 if / else 문을 이용하여 파일이나 디렉터리의 존재 여부를 파악하는 방법, 환경 변수의 정의 여부를 파악하고 그 값을 파악하는 방법, 프로그램이나 배치 파일의 수행 결과를 if 문으로 파악하는 방법 등을 다뤄보기로 하겠습니다. :-)