如何在powershell中循环直到成功?

时间:2011-11-30 21:53:14

标签: iis powershell appcmd

%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因为WebSite尚未启动而无法执行,我将在CBLog.log文件中收到以下错误消息。

  

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

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

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

非常感谢,

更新

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

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

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

  

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

 & $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
    }
}

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

2 个答案:

答案 0 :(得分:4)

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

确保在运行appcmd并在同一脚本中立即检查此变量。如果没有,您冒险从powershell.exe而不是从appcmd.exe

获取exitcode

答案 1 :(得分:0)

我意识到最初的问题很可能已经解决了,但是为了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