8

我在批处理文件中有许多启动任务。特别是我调用 IISappcmd.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']
4

5 回答 5

4

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

于 2012-08-04T19:07:02.023 回答
3

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

'appcmd.exe 列表配置-详细信息'

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

于 2012-08-04T18:10:02.437 回答
3

MSDN 现在包含一个很好的指南,通过处理来自 APPCMD 的错误代码来执行此操作。

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

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

IF %ERRORLEVEL% EQU 183 DO VERIFY > NUL

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

于 2012-10-17T00:11:00.977 回答
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%
)
于 2012-08-06T17:39:35.667 回答
0

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

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

于 2015-03-27T17:29:03.580 回答