3

我现在正在研究厨师食谱,我需要根据代码的结果用一些信息更新数据包。基本上我需要更新一个成功或失败的数据包。

代码如下所示:

begin
     node[:fileDeploy].each do |f|
        if f[:deploy]
          cookbook_file "#{f[:subdirectory]}/#{f[:targetFilename]}" do
             owner users['tomcatUser']
             group users['tomcatGroup']
             mode "0755"
             cookbook node[:cookbookName]
             source "#{f[:sourceFilename]}"
          end
        end
     end
     # Update data bag: succeeded
rescue Chef::Exceptions::FileNotFound => e
     # Update data bag: failed
end

问题是即使有一个丢失的文件,救援块也没有被执行,数据包也没有相应地更新。因此,当我在服务器上运行命令 sudo chef-client 时,它以异常结束,Chef::Exceptions::FileNotFound但它没有被rescue块处理。是否有意义?有什么帮助吗?

4

1 回答 1

6

您的救援块不会捕获异常,因为引发异常的代码未在异常处理程序的范围内执行。

在您的代码中,您声明了一个cookbook_file资源。声明顺利,资源计划在收敛阶段执行。您的救援块可以捕获在资源声明期间发生的异常,而不是在实际执行时发生的异常。

请参阅关于 chef-client Run了解更多关于 chef run 的两个阶段,即资源集合的生成和后期收敛。

现在对于您想要的结果,您可以检查源文件在收敛期间存在的条件并做出相应的决定。

一般来说,在 Chef 中处理错误是相当困难的。这是设计使然,因为您通常应该将系统设计为独立于其他部分。因此,如果您需要存在一个目录或文件,您应该使用适当的资源显式创建该目录或文件。然后,如果当前资源“更改”(无论这对特定资源意味着什么),您可以使用通知来通知其他资源运行特定操作。

下面的代码试图实现与您显然想要的类似的东西。它在收敛期间仍然没有捕获异常,但首先尝试不引发异常,而是检查所需的条件并运行适当的资源。

node[:fileDeploy].each do |f|
  if f[:deploy]
    cookbook_file "#{f[:subdirectory]}/#{f[:targetFilename]}" do
      owner users['tomcatUser']
      group users['tomcatGroup']
      mode "0755"
      cookbook node[:cookbookName]
      source f[:sourceFilename]
      only_if{ Dir.exist?(File.base_name(f[:sourceFilename]) }
      notifies :run, "execute[success #{f[:sourceFilename]}]", :immediately
    end

    # This one gets notified (and run) when the cookbook_file is successful
    execute "success #{f[:sourceFilename]}" do
      action :nothing
      command "do whatever you like"
    end

    # This one runs only if the created file doesn't exist by now
    execute "error #{f[:subdirectory]}/#{f[:targetFilename]}" do
      action :run
      command "do whatever you like"
      creates "#{f[:subdirectory]}/#{f[:targetFilename]}"
    end
  end
end
于 2013-08-23T17:22:15.697 回答