您如何中止/结束 Chef 运行?

Posted

技术标签:

【中文标题】您如何中止/结束 Chef 运行?【英文标题】:How do you abort/end a Chef run? 【发布时间】:2012-12-26 18:10:33 【问题描述】:

在某些情况下,我需要使用非零状态代码中止/结束 Chef 运行,然后它将通过我们的部署链传播回并最终传播到 Jenkins,从而产生一个又大又胖的红球。

最好的方法是什么?

【问题讨论】:

【参考方案1】:

中止或编辑 Chef 运行的推荐方法是引发异常。这是一个例子:

ruby_block "some tricky operation" do
  block do
    OperationFoo
    raise "Operation Foo Failed" if some_condition
  end
end

【讨论】:

【参考方案2】:

对于将来可能不熟悉 Chef 的读者来回答这个问题,Chef 运行“聚合”节点,或使其符合它正在运行的配方中声明的策略.这也称为“收敛”。这有两个阶段,“编译”和“执行”。编译阶段是 Chef 评估(“编译”)食谱的 Ruby 代码,寻找要添加到资源集合中的资源。完成后,它会“执行”每个资源的操作以将其置于所需的状态。系统命令运行等。

Erik Hollensbe 写了一篇优秀的how this works in 2013 演练。

现在,答案是:

有几种方法可以结束 Chef 运行或退出 Chef 配方,具体取决于您的操作方式,因为 Chef 配方是 Ruby 代码。

如果您的目标是根据条件停止处理配方,但继续运行其余部分,请使用 return Ruby 关键字。例如:

file '/tmp/ponies' do
  action :create
end

return if platform?('windows')

package 'bunnies-and-flowers' do
  action :install
end

我们假设如果系统是 Windows,它没有可以安装 bunnies-and-flowers 包的包管理器,所以我们从来的地方返回。

如果您希望完全中止 Chef 运行

Tl;博士:使用raise。如果出现错误情况,最好中止 Chef 运行。

也就是说,如果在运行的任何地方遇到未处理的异常,chef-client 就会退出。例如,如果模板资源找不到它的源文件,或者如果运行 chef-client 的用户没有权限执行诸如创建目录之类的操作。这就是为什么使用raise 也可以结束运行。

你把raise放在哪里很重要。如果您在ruby_block 资源中使用它,它只会在收敛的执行阶段引发。如果您在上面的 return 示例等资源之外使用它,它将在编译阶段发生。

file '/tmp/ponies' do
  action :create
end

raise if platform?('windows')

package 'bunnies-and-flowers' do
  action :install
end

也许我们在 Windows 上确实有一个包管理器,我们希望安装这个包。提升将导致 Chef 致命退出并提供堆栈跟踪。

在过去的几年里,另一种方法是使用 Chef::Application.fatal! - 正如我在这个答案中所写的那样。时代变了,这是不推荐。不要再这样做了。如果您正在这样做,请切换到raise,如前所述,如果您的需求更复杂,请编写自己的异常处理程序(见下文)。

更优雅的错误处理

由于配方是 Ruby,您还可以使用 begin..rescue 块优雅地处理错误情况。

begin
  dater = data_bag_item(:basket, "flowers")
rescue Net::HTTPServerException
  # maybe some retry code here?
  raise "Couldn't find flowers in the basket, need those to continue!"
end

data_bag_item 向 Chef 服务器上的数据包发出 HTTP 请求,如果服务器出现问题(404 未找到、403 未授权等),将返回 Net::HTTPServerException。我们可能会尝试重试或做一些其他处理,然后回退到raise

报告错误

如果您从命令行运行 Chef,只需退出并抛出堆栈跟踪即可。但是,如果您在 cron 中运行它或作为守护程序运行在几台甚至几十台或数百台机器上,那么当出现问题时,这并不是保持理智的好方法。

输入Chef's report/exception handler feature。您可以为 Chef 运行使用处理程序。所有报告处理程序都在 Chef 运行结束时运行。异常处理程序在中止的 Chef 运行结束时运行。运行的状态被跟踪,并且可以在处理程序中检查,因此您可以编写一个处理两种运行(成功/完成或不成功/中止)的程序。

documentation 告诉你如何写一个。它还包括一个可用的open source handlers 列表,您可以将其用于各种服务,包括:

通过 SMTP 发送电子邮件 IRC 石墨 嘻哈聊天

还有更多。

【讨论】:

很棒的答案!非常有帮助。我曾在各种 Chef 资源中寻找过这个,但没有找到。如果我有,这个问题将不存在。最近,我决定,当我在 *** 上或从预期资源中轻松找到问题的答案时,一旦我得到答案,我会整理一个 *** 问答对来记录我学到的东西. 我一直无法让rescue Net::HTTPServerException 工作。它不会挽救异常。 喜欢西班牙宗教裁判所的评论 :-) 所以才叫“converge”! 我在Chef::Application.fatal! 方法中添加了删除线。厨师用户不得使用这种方法,这是一个内部 API,最终会导致错误。例如:github.com/chefspec/chefspec/issues/489#issuecomment-53592637【参考方案3】:

Chef::Application.fatal!应该做你想要的。这是我们代码库中的一个示例,可能会有所帮助。

cipher = case key.length
    when 16 then "AES-128-ECB"
    when 24 then "AES-192-ECB"
    when 32 then "AES-256-ECB"
else
    Chef::Application.fatal!("AES Key must be 16, 24, or 32 characters in length but key #key has length of #key.length")
end

【讨论】:

作为过去 8 年的核心厨师开发人员,请不要在食谱或食谱代码中使用 Chef::Application.fatal!。例如:github.com/chefspec/chefspec/issues/489#issuecomment-53592637 我们也经常遇到直接调用fatal! 导致的异常处理的报告问题。那些我们不能接受为错误的问题,不会被修复,并且不能使用这种方法。规则将很快添加到 foodcritic 中,以警告其使用。您可以将其视为公司的官方推荐。 @lamont 有没有其他方法可以退出配方并告诉后处理程序除了 raise 之外配方失败?我不想使用 raise,因为 raise 会显示整个堆栈跟踪,包括源代码。 我认为您需要使用自定义输出格式化程序来防止显示整个呈现的错误消息。【参考方案4】:

要在 Chef-solo 运行期间进行不干净的退出,请尝试以下操作:

bash 'exit' do
    code 'killall -9 chef-solo'
end

【讨论】:

【参考方案5】:

当您希望chef 在某些操作后完成时,只需使用以下语句:

throw :end_client_run_early

它将退出而没有任何错误。

【讨论】:

以上是关于您如何中止/结束 Chef 运行?的主要内容,如果未能解决你的问题,请参考以下文章

主线程结束后如何保持任务运行?

Chef Recipe 在一台服务器上运行迁移

序列生成器中止时的行为如何?

如何在 componentWillUnmount 中中止运行 async/await xmlHttpRequest?

使用 Python 连接到 Redshift 数据 - 错误:当前事务被中止,命令被忽略,直到事务块结束

开始使用chef,并在部署时运行composer install