【问题标题】:catching return code of a command with "invoke-command" - Powershell 2使用“invoke-command”捕获命令的返回码 - Powershell 2
【发布时间】:2009-07-31 06:23:56
【问题描述】:

我正在使用“invoke-command”在远程机器上执行脚本。

invoke-command -computername <server_name> -scriptblock {command to execute the script}

当出现任何错误时,我的脚本会返回“-1”。 所以,我想通过检查返回码来确保脚本已经成功执行。

我尝试如下。

$code = invoke-command -computername ....

但它什么也没返回。

Invoke-command 不会捕获脚本块的返回码吗?

还有其他方法可以解决这个问题吗?

【问题讨论】:

    标签: powershell return-value


    【解决方案1】:

    我认为,如果您在另一台服务器上以这种方式运行命令,您将无法获得您的脚本的返回码。这是因为Invoke-Command 只是在远程机器上运行一个命令,可能在一个临时会话中,而您无法再次连接到该会话。

    然而,您可以做的是在远程计算机上创建一个会话并在该会话中调用您的脚本。之后,您可以再次检查该会话中的返回值。所以大致如下:

    $s = New-PSSession -ComputerName <server_name>
    Invoke-Command -Session $s -ScriptBlock { ... }
    Invoke-Command -Session $s -ScriptBlock { $? }
    

    可能会奏效。这样您就可以访问与远程计算机上的第一个 Invoke-Command 相同的状态和变量。

    另外Invoke-Command 不太可能通过远程命令的返回值。那你怎么知道Invoke-Command本身失败了?

    ETA:好的,关于“返回码”,我误读了你。我假设你的意思是$?。无论如何,根据文档,您可以在远程计算机上运行脚本,如下所示:

    要在远程计算机上运行本地脚本,请使用 FilePathInvoke-Command的参数。

    例如,以下命令运行Sample.ps1 脚本 在S1S2 计算机上:

    invoke-command -computername S1, S2 -filepath C:\Test\Sample.ps1
    

    脚本的结果返回到本地计算机。你 不需要复制任何文件。

    【讨论】:

    • 在 Jenkins 上下文中运行时 Invoke-command 中的奇怪事情,像这样的返回代码 $returnCode = Invoke-command -file somescript.ps1 将从 somescript.ps1 返回每个。如果在命令窗口中运行,则返回值正确返回。有人知道吗?
    • @koo9: $returnCode 将接收脚本文件的管道输出。不是退出代码。
    • 据说但是在 Jenkins 作业中运行脚本时,$returncode 会以某种方式捕获 ps1 脚本的所有输出
    【解决方案2】:

    这是一个例子......

    远程脚本:

    try {
        ... go do stuff ...
    } catch {
        return 1
        exit
    }
    return 2
    exit
    

    本地脚本:

    function RunRemote {
        param ([string]$remoteIp, [string]$localScriptName)
        $res = Invoke-Command -computername $remoteIp -UseSSL -Credential $mycreds -SessionOption $so -FilePath $localScriptName
        return $res
    }
    
    $status = RunRemote $ip_name ".\Scripts\myRemoteScript.ps1"
    echo "Return status was $status"
    

    如果您完全在信任组中,则不需要 $so、-UseSSL 和 $mycreds。 这似乎对我有用……祝你好运!

    【讨论】:

      【解决方案3】:

      如果远程脚本块返回退出代码,则 psession 将被关闭。我只是在检查 psession 的状态。如果它已关闭,我假设一个错误。有点 hacky,但它适用于我的目的。

      $session = new-pssession $env:COMPUTERNAME
      Invoke-Command -ScriptBlock {try { ErrorHere } Catch [system.exception] {exit 1}} -Session $session
      
      if ($session.State -eq "Closed")
      {
          "Remote Script Errored out"
      }
      
      Remove-PSSession $session
      
      $session = new-pssession $env:COMPUTERNAME
      Invoke-Command -ScriptBlock {"no exitcodes here"} -Session $session
      
      if ($session.State -ne "Closed")
      {
          "Remote Script ran succesfully"
      }
      
      Remove-PSSession $session
      

      【讨论】:

        【解决方案4】:

        如果您需要脚本块的输出退出代码,您可以从块中抛出退出代码,并将 if 转换回调用方的整数...

        $session = new-pssession $env:COMPUTERNAME
        try {
            Invoke-Command -ScriptBlock {Write-Host "This is output that should not be lost"; $exitCode = 99; throw $exitCode} -Session $session
        } catch {
            $exceptionExit = echo $_.tostring()
            [int]$exceptionExit = [convert]::ToInt32($exceptionExit)
            Write-Host "`$exceptionExit = $exceptionExit"
        }
        

        这将返回标准输出和最后的退出代码。但是,这确实需要在您的脚本块中捕获任何异常并将其作为退出代码重新抛出。示例的输出...

        This is output that should not be lost
        $exceptionExit = 99
        

        【讨论】:

        • 错误投反对票。您会编辑您的回复以便我撤消投票吗?
        • 我投了赞成票,不小心对你的答案投了反对票。
        【解决方案5】:

        我正在寻找通过调用命令调用的批处理脚本返回的错误代码。这不是一件容易的事,但我找到了一个很好且简单的方法。

        您的 PowerShell 脚本是 $res=invoke-command -Computername %computer% {C:\TEST\BATCH.CMD} write-host $res 你会发现 $res 是批处理输出,通过使用 @echo off、>nul 和 echo "what you want to return" 知道这一点是可能的!

        你的批处理脚本

        @echo off
        echo "Start Script, do not return" > nul
        echo 2
        

        现在 $res = 2!然后你可以在你的批处理中应用任何逻辑。

        你甚至可以使用 invoke-command -AsJob 使用 Receive-job 获取输出!在这种情况下,您不需要使用 $res。

        干杯, 朱利安

        【讨论】:

          【解决方案6】:

          如果执行脚本的错误代码为零,则下面的最后一个 Powershell Invoke-Command 返回布尔值 True,如果返回代码非零,则返回布尔值 False。非常适合检测远程执行返回的错误代码。

          function executeScriptBlock($scriptString) {
          
              Write-Host "executeScriptBlock($scriptString) - ENTRY"
          
              $scriptBlock = [scriptblock]::Create($scriptString + " `n " + "return `$LASTEXITCODE")
          
              Invoke-Command -Session $session -ScriptBlock $scriptBlock
          
              $rtnCode = Invoke-Command -Session $session -ScriptBlock { $? }
          
              if (!$rtnCode) {
                  Write-Host "executeScriptBlock - FAILED"
              }
              Else {
                  Write-Host "executeScriptBlock - SUCCESSFUL"
              }
          }
          

          【讨论】:

            猜你喜欢
            • 2012-01-22
            • 1970-01-01
            • 2017-08-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-12-21
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多