5
%WINDIR%\system32\inetsrv\appcmd.exe set site /site.name:"WebRole_IN_0_CB" /[Path='/'].applicationPool:"ASP.NET v4.0" >>CBLog.log
powershell.exe -command Set-ExecutionPolicy Unrestricted
powershell.exe .\CheckIfSuccessful.ps1

我想运行上面的脚本,如果 appcmd.exe 由于网站尚未启动并准备好而无法执行它,我将在 CBLog.log 文件中收到以下错误消息。

错误(消息:找不到标识符为“WebRole_IN_0_CB”的站点对象。)

在 CheckIfSuccessful.ps1 中,我想创建一个用于循环的 Powershell 脚本,该脚本运行 appcmd 命令并再次检查错误。然后休眠5秒,然后重试,直到成功。

我将如何在 Powershell 中执行此操作?

高度赞赏,

更新:

好的,非常感谢 $lastexitcode 的提示,虽然它看起来很有希望。看来我在 Powershell 中转换单引号时遇到问题:(以下是我最初的 appcmd 命令的一部分)

/[Path='/'].applicationPool:"ASP.NET v4.0"

我如何在powershell中引用这个?我试图简化它,以便 powershell 减少它的麻烦,但现在我的命令似乎是错误的,正如它现在所说的那样:

错误(消息:找不到标识符为“v4.0”的站点对象。)

 & $Env:WinDir\system32\inetsrv\appcmd.exe set site '/site.name:"WebRole_IN_0_CB"' "/[Path='/'].applicationPool:`"ASP.NET v4.0`"" >CBLog.log
if($lastexitcode -ne '0')
{
    while($lastexitcode -ne '0')
    {
        Start-Sleep -s 5
        & $Env:WinDir\system32\inetsrv\appcmd.exe set site '/site.name:"WebRole_IN_0_CB"' "/[Path='/'].applicationPool:`"ASP.NET v4.0`"" >CBLog.log
    }
}

更新二: 我已经正确地逃脱了它。但我仍然收到错误消息。如果我在创建该站点后单独运行 appcmd,那么日志文件就可以了。请问有什么建议吗?

4

2 回答 2

5

特殊变量$lastexitcode为您提供上次运行的本机可执行文件(即不是 cmdlet)的退出代码。根据操作的结果,这将具有不同的值。例如,如果 appcmd 遇到拒绝访问,则为 5。如果最后一个命令成功完成,它应该为 0。

确保在运行 appcmd 后立即在同一脚本中检查此变量。如果没有,您可能会从 powershell.exe 而不是从 appcmd.exe 获取退出代码

于 2011-12-01T01:21:52.490 回答
3

我意识到最初的问题可能早就解决了,但是为了让 Google 员工解决这个问题,我编写了一个通用(高级)函数来重试 shell(cmd)命令。除了 $LASTEXITCODE 它还可以解析错误流(使用一些工具,退出代码可能是谎言)。

function Call-CommandWithRetries
{
 [CmdletBinding()]
 param( 
     [Parameter(Mandatory=$True)]
     [string]$Command,
     [Array]$Arguments,
     [bool]$TrustExitCode = $True,
     [int]$RetrySleepSeconds = 10,
     [int]$MaxAttempts = 10,
     [bool]$PrintCommand = $True
 )

 Process
 {
  $attempt = 0
  while ($true)
  {   
   Write-Host $(if ($PrintCommand) {"Executing: $Command $Arguments"} else {"Executing command..."}) 
   & $Command $Arguments 2>&1 | tee -Variable output | Write-Host

   $stderr = $output | where { $_ -is [System.Management.Automation.ErrorRecord] }
   if ( ($LASTEXITCODE -eq 0) -and ($TrustExitCode -or !($stderr)) )
   {
    Write-Host "Command executed successfully"
    return $output
   }

   Write-Host "Command failed with exit code ($LASTEXITCODE) and stderr: $stderr" -ForegroundColor Yellow
   if ($attempt -eq $MaxAttempts)
   {
    $ex = new-object System.Management.Automation.CmdletInvocationException "All retry attempts exhausted"
    $category = [System.Management.Automation.ErrorCategory]::LimitsExceeded
    $errRecord = new-object System.Management.Automation.ErrorRecord $ex, "CommandFailed", $category, $Command
    $psCmdlet.WriteError($errRecord)
    return $output
   }

   $attempt++;
   Write-Host "Retrying test execution [#$attempt/$MaxAttempts] in $RetrySleepSeconds seconds..."
   Start-Sleep -s $RetrySleepSeconds
  }
 }
}

有关更多信息(包括完整文档),请参阅https://www.ohadsoft.com/2016/04/invoking-arbitrary-shell-cmd-commands-in-powershell

在你的情况下,你会做类似的事情

$appCmd = [io.path]::combine($env:WINDIR, 'system32', 'inetsrv', 'appcmd.exe')
$appCmdArg = @('set', 'site', '/site.name:"WebRole_IN_0_CB"', '/[Path=''/''].applicationPool:"ASP.NET v4.0"')
$output = Call-CommandWithRetries $appCmd $appCmdArgs
# write $output to log etc
于 2016-04-18T16:07:26.300 回答