【问题标题】:How to make startup tasks idempotent?如何使启动任务具有幂等性?
【发布时间】:2023-03-26 19:40:02
【问题描述】:

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

【问题讨论】:

  • 很确定应该阻止未使用的 AppPools 自动启动的行将不起作用。而不是使用“Classic .NET AppPool”等作为您需要使用 Clr2ClassicAppPool 等的名称。
  • 实际上这些名称工作正常,但它确实需要稍微不同地引用。我已经更新了上面的代码,以防有人稍后查看。

标签: iis azure dos appcmd


【解决方案1】:

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

'appcmd.exe list config -details'

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 似乎是个好主意。知道如何在 .cmd 脚本中实现它吗?我相信我最终会弄明白的,但听起来你以前可能做过类似的事情。
    • 万一以后有人读到这个,我在另一个答案中添加了代码来实现这个。
    【解决方案3】:

    根据 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%
    )
    

    【讨论】:

    • 您也应该将%ComputerName% 放在标志文件名中! ..会有用的!
    • 为什么会有用?
    【解决方案4】:

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

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

    基本上在任何appcmd操作之后,你都可以做到以下几点:

    IF %ERRORLEVEL% EQU 183 DO VERIFY > NUL
    

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

    【讨论】:

    • 非常好。似乎这可能是“正确”的做法。太糟糕了,错误处理太冗长了。
    • 这似乎是 MSDN 文章中的错误 - 'DO' 过多,因为 'IF' 命令的语法是:'IF [/I] string1 compare-op string2 command'。 DO 关键字仅适用于“FOR”命令。所以正确的命令应该看起来像:'IF %ERRORLEVEL% EQU 183 VERIFY > NUL'。这个对我有用,而原版破坏了脚本,阻止了角色的开始。
    【解决方案5】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-05
      • 1970-01-01
      • 2020-05-08
      • 2018-03-05
      • 1970-01-01
      • 2023-03-19
      • 2014-08-17
      • 2019-05-23
      相关资源
      最近更新 更多