2012-08-04 58 views
7

我在批處理文件中有許多啓動任務。特別是我調用IIS的appcmd.exe來配置IIS。 Azure中的啓動任務應該是冪等的(即,能夠以相同的結果重複運行),以防由於某種原因重新啓動角色。不幸的是,我的許多IIS配置命令第二次都會失敗,例如,因爲他們第一次刪除了一個配置節點,而後來這些配置節點沒有出現在後續運行中。如何使啓動任務具有冪等性?

我的問題是,我如何使這些啓動任務idempotent?有沒有辦法讓appcmd.exe不會拋出錯誤?有沒有辦法讓shell捕獲錯誤?有沒有辦法讓Azure框架忽略錯誤?

下面是我的啓動任務的示例。這全部包含在命令文件configiis.cmd中。

@REM Enable IIS compression for application/json MIME type 
%windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/httpCompression /+"dynamicTypes.[mimeType='application/json',enabled='True']" /commit:apphost 
%windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/httpCompression /+"dynamicTypes.[mimeType='application/json; charset=utf-8',enabled='True']" /commit:apphost 

@REM Set IIS to automatically start AppPools 
%windir%\system32\inetsrv\appcmd.exe set config -section:applicationPools -applicationPoolDefaults.startMode:AlwaysRunning /commit:apphost 

@REM Set IIS to not shut down idle AppPools 
%windir%\system32\inetsrv\appcmd set config -section:applicationPools -applicationPoolDefaults.processModel.idleTimeout:00:00:00 /commit:apphost 

@REM But don't automatically start the AppPools that we don't use, and do shut them down when idle 
%windir%\system32\inetsrv\appcmd.exe set config -section:system.applicationHost/applicationPools "/[name='Classic .NET AppPool'].startMode:OnDemand" "/[name='Classic .NET AppPool'].autoStart:False" "/[name='Classic .NET AppPool'].processModel.idleTimeout:00:01:00" /commit:apphost 
%windir%\system32\inetsrv\appcmd.exe set config -section:system.applicationHost/applicationPools "/[name='ASP.NET v4.0'].startMode:OnDemand" "/[name='ASP.NET v4.0'].autoStart:False" "/[name='ASP.NET v4.0'].processModel.idleTimeout:00:01:00" /commit:apphost 
%windir%\system32\inetsrv\appcmd.exe set config -section:system.applicationHost/applicationPools "/[name='ASP.NET v4.0 Classic'].startMode:OnDemand" "/[name='ASP.NET v4.0 Classic'].autoStart:False" "/[name='ASP.NET v4.0 Classic'].processModel.idleTimeout:00:01:00" /commit:apphost 


@REM remove IIS response headers 
%windir%\system32\inetsrv\appcmd.exe set config /section:httpProtocol /-customHeaders.[name='X-Powered-By'] 
+0

很確定應該阻止未使用的AppPools自動啓動的行不起作用。而不是使用'Classic .NET AppPool'等作爲您需要使用Clr2ClassicAppPool等的名稱。 – 2012-10-16 23:56:25

+0

其實這些名字都能正常工作,但確實需要引用一點不同。我更新了上面的代碼,以防有人在以後看到它。 – 2012-10-26 18:07:48

回答

4

除了@ Syntaxc4的答案:考慮在本地使用麪包屑(文件)。在您的腳本中,檢查是否存在已知文件(您創建的文件)。如果它不存在,請檢查啓動腳本,並創建一個麪包屑文件。下次啓動vm時,它會再次檢查breadcrumb文件的存在,如果存在,請退出cmd文件。如果麪包屑文件消失,這通常意味着您的虛擬機已在其他位置重新構建(可能是新實例或重新生成的實例可能位於不同硬件上),並且需要IIS配置。

+0

看起來像個好主意。任何想法如何在.cmd腳本中實現?我相信我可以最終弄明白,但聽起來你以前可能做過這樣的事情。 – 2012-08-04 21:38:41

+0

如果有人在將來閱讀此內容,我添加了代碼以在另一個答案中實現此目的。 – 2012-08-06 17:40:37

3

你會檢查,看看是否配置設置是試圖將其刪除之前存在(添加條件邏輯)。這可以通過以下方式實現:

「Appcmd.exe的列表配置-details」

捕捉返回值會給你的東西來比較,無論是輸出的長度或實際值。

2

根據David Makogon的建議,我在每個.cmd文件的頂部添加了以下內容。這似乎有伎倆。它會在與執行腳本相同的目錄中創建一個標誌文件(David稱爲麪包屑文件),然後在隨後的運行中檢查它。

@REM A file to flag that this script has already run 
@REM because if we run it twice, it errors out and prevents the Azure role from starting properly 
@REM %~n0 expands to the name of the currently executing file, without the extension 
SET FLAGFILE=c:\%~n0-flag.txt 

IF EXIST "%FLAGFILE%" (
    ECHO %FLAGFILE% exists, exiting startup script 
    exit /B 
) ELSE (
    date /t > %FLAGFILE% 
) 
+0

你應該在標誌文件名中加入'%ComputerName%'! ..會很有用! – wasatchwizard 2013-10-08 21:31:36

+0

爲什麼這會有用? – 2013-10-08 21:33:34

3

MSDN現在包含一個很好的指導,通過處理來自APPCMD的錯誤代碼來做到這一點。

http://msdn.microsoft.com/en-us/library/windowsazure/hh974418.aspx

基本上任何APPCMD操作之後,你可以做到以下幾點:

IF %ERRORLEVEL% EQU 183 DO VERIFY > NUL 

和忽略任何可接受的錯誤代碼。

+0

非常好。似乎這可能是「正確」的做法。錯誤處理太糟糕了。 – 2012-10-17 14:17:39

+1

這似乎是MSDN文章中的一個錯誤 - 'DO'過多,因爲'IF'命令的語法爲: 'IF [/ I] string1 compare-op string2 command'。 而DO關鍵字僅適用於'FOR'命令。所以正確的命令應該如下所示: 'IF%ERRORLEVEL%EQU 183 VERIFY> NUL'。 這一個爲我工作,而原來打破了腳本阻止角色從一開始。 – Vertigo 2013-09-24 08:47:42

0

我強烈建議在list命令的末尾使用/config:* /xml。欲瞭解更多關於我如何製作iis idempotent的信息,請看看:https://github.com/opscode-cookbooks/iis

廚師是多個配置管理平臺之一,我只是建議看看代碼(紅寶石),通過列出當前設置並將它們與請求更改的設置進行比較。