【问题标题】:Puppet 5.3.3 and Powershell - returned 1 instead of one of [0]Puppet 5.3.3 和 Powershell - 返回 1 而不是 [0] 之一
【发布时间】:2018-07-05 17:06:02
【问题描述】:

自从迁移到 Puppet 5.3.3 后,我在运行任何启动或调用进程的 powershell 脚本时都遇到了 puppet 退出代码 1。例如,我有一个打开记事本的 powershell 脚本:

Write-Host "Starting notepad ..."
[System.Diagnostics.Process] $proc = Start-Process -FilePath notepad -PassThru -Wait -ErrorAction stop
$EXIT_CODE=$proc.exitcode
Write-Host "notepad exit code is (${EXIT_CODE})"

直接在 Powershell 中运行此脚本即可完成 OK 并返回预期结果。通过以下 Puppet 清单运行时,我收到错误“返回 1 而不是 [0] 之一”

Exec {
  provider  => powershell,
}

exec { 'test':
  command   => 'C:/build/test.ps1',
  timeout   => '0',
  logoutput => true,
}

这在 Puppet 4.x 上没有问题。它执行第一个 Write-Host 和 Start-Process 函数,但在进程完成后退出。完整错误如下:

[Notice: /Stage[main]/Ingres::Win_installation/Exec[test]/returns: Starting notepad ...
[Notice: Applied catalog in 23.19 seconds
[Error: 'C:/build/test.ps1 notepad' returned 1 instead of one of [0]
[Error: /Stage[main]/Ingres::Win_installation/Exec[test]/returns: change from 'notrun' to ['0'] failed: 'C:/build/test.ps1 notepad' returned 1 instead of one of [0]

任何帮助表示赞赏!

【问题讨论】:

    标签: powershell puppet


    【解决方案1】:

    我认为问题在于超时 => 0。 我看了一下PowerShell的源代码:https://github.com/puppetlabs/puppetlabs-powershell/blob/7c8f2464dff5ce8bfd806fa900c8ff8985de5c50/lib/puppet/provider/exec/powershell.rb#L91

    如果你传递 0,它实际上会等待 0 秒然后使 puppet 失败。如果去掉 timeout 参数,默认为 300 秒(https://github.com/puppetlabs/puppetlabs-powershell/blob/master/lib/puppet_x/puppetlabs/powershell/powershell_manager.rb#L151)。

    由于他们使用的是管道(没有使用过,所以我可能错了:https://msdn.microsoft.com/library/bb355337(v=vs.110).aspx)超时是必需的参数,因此唯一的解决方案是增加超时。

    【讨论】:

      【解决方案2】:

      Puppet PowerShell module in Github 的指南实际上指出了这一点。建议的解决方案是始终在 PowerShell 脚本末尾添加明确的 Exit 语句来控制退出代码:

      外部文件和退出代码

      如果您正在调用外部文件,例如 与其他 PowerShell 脚本或可执行文件一样,请注意最后一个 Puppet 使用执行脚本的退出代码来确定是否 命令成功。

      例如,如果文件 C:\fail.ps1 包含以下 PowerShell 脚本:

      & cmd /c EXIT 5 & cmd /c EXIT 1 我们使用以下 Puppet 清单:

      exec { 'test':
        command   => '& C:\fail.ps1',
        provider  => powershell,
      }
      

      那么exec['test'] 资源总是会失败,因为 外部文件 C:\fail.ps1 的最后一个退出代码是 1。这个 如果将多个行为结合起来,可能会产生意想不到的后果 外部文件。

      要停止这种行为,请确保在 您的 PowerShell 脚本。例如,我们更改了 Puppet 清单 从上面到:

      exec { 'test':
        command   => '& C:\fail.ps1; Exit 0',
        provider  => powershell,
      }
      

      这将始终成功,因为 Exit 0 语句 覆盖 C:\fail.ps1 脚本的退出代码。

      -- https://github.com/puppetlabs/puppetlabs-powershell#external-files-and-exit-codes

      我建议也许用 Try..Catch 来做这个:

      Try {
         .. your code ..
         Exit 0
      } Catch {
         Write-Error $_
         Exit 1
      }
      

      【讨论】:

      • 感谢您的反馈。我已将 PowerShell 脚本更改为使用 Try..Catch,将 Exit 0 分配给 Try,将 Exit 1 分配给 catch。通过 Puppet manifest 运行它时,我得到了相同的结果,如我原来的问题所示。我宁愿避免显式退出语句,因为这会掩盖脚本本身的任何问题。
      • 是的,我正在尝试复制并看到相同的结果。这似乎与start-process 有关,就好像你只是调用一个.exe 而没有它然后你可以用exit 控制退出代码但似乎当你使用start-process 时添加exit 并没有什么不同。
      • 我也尝试过使用 Invoke-WmiMethod Win32_Process 而不是 start-process 但结果相同。就好像 puppet 认为这些命令运行后目录已完成应用并忽略任何后续命令。
      • 我认为问题在于超时 => 0。我查看了 PowerShell 的源代码 (github.com/puppetlabs/puppetlabs-powershell/blob/…)。如果你传递 0,它实际上会等待 0 秒然后使 puppet 失败。如果您删除 timeout 参数,则默认值为 300 秒 (github.com/puppetlabs/puppetlabs-powershell/blob/master/lib/…)。 :msdn.microsoft.com/library/bb355337(v=vs.110).aspx
      • 有趣!您可能应该将其添加为附加答案,以便对未来的读者有更大的知名度。
      猜你喜欢
      • 2016-06-12
      • 1970-01-01
      • 2018-05-05
      • 2012-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-03
      • 2016-05-06
      相关资源
      最近更新 更多