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

时间:2022-09-11 19:55:44

I have a number of startup tasks in batch files. In particular I call IIS's appcmd.exe to configure IIS. Startup tasks in Azure are supposed to idempotent (ie, able to be run repeatedly with the same results), in case the role is restarted for some reason. Unfortunately many of my IIS configuration commands will fail the second time around, eg because they delete a configuration node the first time which is then not present on subsequent runs.

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

My question is, how do I make these startup tasks idempotent? Is there a way to make appcmd.exe not throw errors? Is there a way to make the shell catch the errors? Is there a way to make the Azure framework ignore the errors?

我的问题是,如何使这些启动任务具有幂等性?有没有办法让appcmd.exe不抛出错误?有没有办法让shell捕获错误?有没有办法让Azure框架忽略错误?

Here's an example of my startup tasks. This is all contained in a command file, configiis.cmd.

这是我的启动任务的一个例子。这都包含在命令文件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 个解决方案

#1


4  

Aside from @Syntaxc4's answer: Consider the use of a breadcrumb (file) locally. In your script, check for existence of a known file (that you create). If it doesn't exist, go through your startup script, also creating a breadcrumb file. Next time the vm starts up, it would again check for existence of the breadcrumb file and, if it exists, exit the cmd file. If the breadcrumb file disappears, this typically means your vm has been reconstituted somewhere else (either a new instance or a respawned instance maybe on different hardware) and IIS configuration would be needed.

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

#2


3  

You would have to check to see if the config setting is present before attempting to delete it (add conditional logic). This could be achieved by:

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

'appcmd.exe list config -details'

'appcmd.exe list config -details'

Capturing a return value would give you something to compare against, be it length of output or an actual value.

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

#3


3  

MSDN now contains an excellent guide for doing this by handling error codes from APPCMD.

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

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

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

Basically after any appcmd operation, you can do the following:

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

IF %ERRORLEVEL% EQU 183 DO VERIFY > NUL

and ignore any acceptable error code.

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

#4


2  

Based on David Makogon's suggestion, I added the following to the top of each of my .cmd files. This seems to do the trick. It will create a flag file (what David called a breadcrumb file) in the same directory as the executing script, then check for it on subsequent runs.

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

#5


0  

I highly recommend using the /config:* /xml on the end of your list command. For more information on how I made iis idempotent please look at: https://github.com/opscode-cookbooks/iis

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

Chef is one of multiple configuration management platforms and i'm only suggesting looking at it for the code (in ruby) that does idempotent via listing the current settings and comparing them to the settings being requested to change.

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

#1


4  

Aside from @Syntaxc4's answer: Consider the use of a breadcrumb (file) locally. In your script, check for existence of a known file (that you create). If it doesn't exist, go through your startup script, also creating a breadcrumb file. Next time the vm starts up, it would again check for existence of the breadcrumb file and, if it exists, exit the cmd file. If the breadcrumb file disappears, this typically means your vm has been reconstituted somewhere else (either a new instance or a respawned instance maybe on different hardware) and IIS configuration would be needed.

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

#2


3  

You would have to check to see if the config setting is present before attempting to delete it (add conditional logic). This could be achieved by:

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

'appcmd.exe list config -details'

'appcmd.exe list config -details'

Capturing a return value would give you something to compare against, be it length of output or an actual value.

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

#3


3  

MSDN now contains an excellent guide for doing this by handling error codes from APPCMD.

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

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

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

Basically after any appcmd operation, you can do the following:

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

IF %ERRORLEVEL% EQU 183 DO VERIFY > NUL

and ignore any acceptable error code.

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

#4


2  

Based on David Makogon's suggestion, I added the following to the top of each of my .cmd files. This seems to do the trick. It will create a flag file (what David called a breadcrumb file) in the same directory as the executing script, then check for it on subsequent runs.

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

#5


0  

I highly recommend using the /config:* /xml on the end of your list command. For more information on how I made iis idempotent please look at: https://github.com/opscode-cookbooks/iis

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

Chef is one of multiple configuration management platforms and i'm only suggesting looking at it for the code (in ruby) that does idempotent via listing the current settings and comparing them to the settings being requested to change.

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