【问题标题】:Jenkins powershell plugin always builds successfullyJenkins powershell 插件总是成功构建
【发布时间】:2016-03-24 19:00:06
【问题描述】:

我正在使用 Jenkins PowerShell 插件来构建一个项目。

但是,我发现无论我在 Windows PowerShell 命令中输入什么内容,Jenkins 总是认为我的构建成功。

这是一个例子:

如您所见,asdf 不是合法命令。 Jenkins 应该在构建后给我FAILURE

但是控制台输出给了我:

Started by user admin
Building in workspace C:\Users\Administrator\.jenkins\jobs\Test\workspace
[workspace] $ powershell.exe -NonInteractive -ExecutionPolicy ByPass "& 'C:\Users\ADMINI~1\AppData\Local\Temp\hudson2092642221832331776.ps1'"
The term 'asdf' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At C:\Users\ADMINI~1\AppData\Local\Temp\hudson2092642221832331776.ps1:1 char:5
+ asdf <<<< 
    + CategoryInfo          : ObjectNotFound: (asdf:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

Finished: SUCCESS

我认为PowerShell的执行结果应该取决于$lastexitcode

这是 PowerShell 插件的错误吗?

【问题讨论】:

  • 发生错误时,在您的 powershell 脚本中使用“exit x”,其中 x 是一个非零数。看看詹金斯是否认为它失败了。
  • 是的,Jenkins 认为 exit 1 失败。
  • 然后更改您的脚本以在发生错误时以非零错误代码退出。如果您希望它仅依赖于 $lastexitcode,那么在脚本底部检查 $lastexitcode 并在适用时使用 exit 1。
  • 最后,我在脚本末尾添加exit $LastExitCode

标签: powershell jenkins jenkins-plugins


【解决方案1】:

从 1.3 开始,插件将不会处理诸如缺少命令的异常。您可以通过try/catch 自己完成此操作:

try
{
    asdf
}
catch
{
    write-host "Caught an exception"
    exit 1
}

请参阅MSDN 了解更多信息。

【讨论】:

  • 感谢您的回答!为了将实际错误输出到构建控制台,我在 catch 中执行write-host $error
【解决方案2】:

对我来说,我希望脚本在遇到错误时立即停止并在 Jenkins 中失败。这是通过将其添加到脚本的开头来完成的:

$ErrorActionPreference = "停止"

此处对此进行了讨论:[如何在第一个错误时停止 PowerShell 脚本?][1]

[1]:How to stop a PowerShell script on the first error?。 .....

【讨论】:

  • 这是唯一对我有用的解决方案。我正在将变量注入脚本,并且除了错误之外一切正常。当 PS 脚本出现错误时,这最终将构建标记为失败。谢谢!
  • 这在声明性管道中对我不起作用:脚本:$ErrorActionPreference = "Stop" asdffails 在 powershell 中,但不会使管道失败。管道:steps { powershell(returnStatus: true, script: 'psscripts/psScript1.ps1') } 我必须将其放入脚本块中并测试返回值以使其失败。
【解决方案3】:

根据最新版本的插件 (Version 1.3 Sept 18 2015),您必须使用 $LastExitCode 才能使构建失败。

1.3 版(2015 年 9 月 18 日)

  • PowerShell 现在以非交互模式运行,以防止交互提示挂起构建
  • PowerShell 现在运行时将 ExecutionPolicy 设置为“绕过”以避免执行策略问题
  • 脚本现在以 $LastExitCode 退出,导致非零退出代码将构建标记为失败
  • 添加了帮助和可用环境变量列表(包括英语和法语翻译)

【讨论】:

  • 此答案仅与插件的发行说明相呼应,似乎无法准确反映插件的操作。注释说“脚本现在以 $LastExitCode 退出”,我读为“当插件将您的命令复制到 .ps1 文件以执行时,它会将 exit $LastExitCode 添加到生成脚本的末尾,以便 Jenkins 捕获并做出反应失败。”这正是发生的情况,因此不需要手动添加 exit 行。但是,即使生成了 exit,无效命令也不会导致构建失败。
  • @ChrisNelson 从您发布的链接中...... “要捕获此退出代码,请使用 $LastExitCode PowerShell 变量。” 然而,我的回复被接受为回答。我不同意添加“退出”命令的需要。
  • 我也不同意添加exit 的必要性。该插件可以做到这一点。 OP想知道如何处理asdf,我注意到找不到的命令没有设置$LastExitCode,它会引发异常。
  • @ChrisNelson 我认为您可能误解了原始问题的上下文。您应该尝试在 Jenkins 中运行脚本并尝试获取退出代码。我想你会发现你的假设是不正确的。
  • 我对我可能不理解的内容感到困惑。如果您只将asdf 放入命令区域并进行构建,插件会发出一个包含asfdexit $LastExitCode 的两行脚本。由于asdf 抛出异常且未设置$LastExitCode,因此构建成功。添加显式的exit $LastExitCode 会导致发出的脚本在第一行带有asdf,然后是两个exit 行。我确实看到,如果我提供了一个失败的有效命令,则会设置 $LastExitCode,但这似乎并没有解决 OP 的示例。
【解决方案4】:

我想在这里补充一下,我刚刚遇到了一个怪癖:您必须让 powershell 脚本以 exit 而不是 return 结尾。

我的詹金斯管道看起来像:

script {
  result = powershell(returnStatus: true, script: '''...if(error condition) { return 1 }''')
  
  if(result) { error }
}

我使用的是if(error condition) { return 1 },虽然 1 在 jenkins 控制台中显示为返回值,但它没有构建失败。当我使用if(error condition) { exit 1 } 时,构建按预期失败。

我认为这是对该线程的有益补充 - 需要使用 exit 而不是 return。但我不明白这部分:管道正在检查result 是否为非零。使用 return 时导致 if(result) { error } 无法按预期工作的 powershell 指令中的 exitreturn 有什么区别?

2021 年 2 月 16 日更新: 回到这一点,根据我的经验添加更多注释:我认为我在做的事情以及很多人做的事情都让人困惑,就是使用returnStdoutreturnStatus 并且不检查它们和/或不完全了解返回的内容。

如果您使用其中任何一个参数,Jenkins 将不会根据它们的价值为您做任何事情。你必须自己检查它们并采取相应的行动。另一方面,如果您使用它们,Jenkins 识别失败代码并在返回时使管道失败。

想一想:如果您设置returnStatus,您将从步骤中获取退出代码作为返回值,而不是让 Jenkins 自己担心。如果您设置了returnStdout,您将获得stdout 流——并且没有任何错误代码或来自stderr 的任何内容。所以你必须检查你想要的回报,否则你不会得到你期望的行为。

我一直在做的实际上是没有设置这些参数中的任何一个,并确保在我的管道中运行的任何和所有 PowerShell 脚本的开头设置$ErrorActionPreference = 'Stop'。这样,任何 powershell 故障都会按预期自动使管道失败,而无需检查它。

【讨论】:

  • 回答我自己的问题,我认为区别在于return 通过stdout 返回,而exit 设置脚本的退出代码。此外,exit 1 表示“我失败了”,而return 1 表示“这是给你的 1”。最后,returnStatus 正在寻找嵌入脚本(特别是 $LASTEXITCODE)的成功/失败。因此,returnStatusexit 1 将报告失败。如果我想使用returnStdout那么return 1 会起作用,因为它会通过stdout
【解决方案5】:

这就是我实施 RRIROWER 解决方案的方式。希望能帮助到你。

<yourscript>.ps1; exit $lastexitcode

确保您的 powershell 脚本确实以所需的值退出。
最后一行运行"exit &lt;value&gt;"

【讨论】:

    【解决方案6】:

    最终,我不得不在 Jenkins 中使用以下配置,因为这里的解决方案都不适合我。克里斯纳尔逊的回答让我走上了正轨。我们正在远程调用 chef-client,所以我们必须做一点魔法来让远程 PS 会话与本地对话,然后将状态传递给 Jenkins。

    • $res 给出了 chef-client 的输出。
    • $lastsuccess 根据参与的 PS 规则是真还是假。

    当然,您必须提供自己的环境变量! :)

     Write-host "Deploying $env:Computer with $env:Databag data bag... "
     $secstr = ConvertTo-SecureString $env:Password -AsPlainText -Force 
     $cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $env:User, $secstr
     $s = New-PSSession -ComputerName $env:Computer  -Credential $cred
     $res = Invoke-Command -Session $s -ScriptBlock { try {chef-client} catch {exit 1}}
     $lastsuccess = Invoke-Command -Session $s -ScriptBlock {$?}
     Remove-PSSession $s
     write-host " --- "
     write-host $res
     write-host " --- "
     if($lastsuccess)
     {
      write-host "chef deployment completed"
      exit 0
     }
     write-host "chef deployment had errors"
     exit 1
    

    【讨论】:

      猜你喜欢
      • 2012-12-08
      • 1970-01-01
      • 2013-03-28
      • 2016-04-08
      • 2017-10-29
      • 1970-01-01
      • 1970-01-01
      • 2013-04-17
      • 2018-04-27
      相关资源
      最近更新 更多