如何使启动任务具有幂等性?

时间:2012-08-04 17:48:58

标签: iis azure dos appcmd

我在批处理文件中有许多启动任务。特别是我调用IIS的appcmd.exe来配置IIS。 Azure中的启动任务应该是幂等的(即,能够以相同的结果重复运行),以防角色由于某种原因重新启动。不幸的是,我的许多IIS配置命令第二次都会失败,例如因为它们第一次删除配置节点,然后在后续运行中不存在。

我的问题是,如何使这些启动任务具有幂等性?有没有办法让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']

5 个答案:

答案 0 :(得分:4)

除了@ Syntaxc4之外的答案:考虑在本地使用面包屑(文件)。在脚本中,检查是否存在已知文件(您创建的文件)。如果它不存在,请查看启动脚本,同时创建面包屑文件。下次vm启动时,它将再次检查是否存在breadcrumb文件,如果存在,则退出cmd文件。如果breadcrumb文件消失,这通常意味着您的vm已在其他地方重新构建(新实例或重新生成的实例可能在不同的硬件上),并且需要进行IIS配置。

答案 1 :(得分:3)

在尝试删除配置设置之前,您必须检查配置设置是否存在(添加条件逻辑)。这可以通过以下方式实现:

'appcmd.exe list config -details'

捕获一个返回值会给你一些可以比较的东西,无论是输出长度还是实际值。

答案 2 :(得分:3)

MSDN现在包含一个很好的指南,可以通过处理来自APPCMD的错误代码来实现此目的。

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

基本上在任何appcmd操作之后,您可以执行以下操作:

IF %ERRORLEVEL% EQU 183 DO VERIFY > NUL

并忽略任何可接受的错误代码。

答案 3 :(得分:2)

根据David Makogon的建议,我在每个.cmd文件的顶部添加了以下内容。这似乎可以解决问题。它将在与执行脚本相同的目录中创建一个标志文件(David称为breadcrumb文件),然后在后续运行中检查它。

@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%
)

答案 4 :(得分:0)

我强烈建议您在/config:* /xml命令的末尾使用list。有关我如何使iis成为幂等的更多信息,请查看:https://github.com/opscode-cookbooks/iis

Chef是多个配置管理平台之一,我只是建议通过列出当前设置并将它们与要求更改的设置进行比较来查看代码(在ruby中)以进行幂等。