阻止厨师菜谱执行先前执行的操作?

阻止厨师菜谱执行先前执行的操作?

我有一个简单的配方,如下所示,目前我正在使用本地文件来指示命令是否已运行

execute "test" do
  command "sh test.sh && touch /opt/myapp/done.log"
  only_if {File.exists?("/opt/myapp/done.log")}
end

有没有更好的方法?这是推荐的方法吗?

答案1

这通常是我使用的方法,特别是如果您执行的命令导致文件作为副作用被创建时,例如,禁用或启用 Debian 的 apache2 包中的站点会删除或创建/etc/apache2您可以在其中测试使用的链接File.exists?

一个技巧是在执行资源运行后设置一个属性:

if !node["did_test"]
  execute "test" do
    command "touch /tmp/foo"
  end
end

ruby_block "did_test" do
  block do
    node.default["did_test"] = true
  end
end

请注意,在某些情况下执行资源仍有可能运行两次,因此这种技术并不完美,但您现在可以使用 knife-search 来确定哪些节点执行了执行。

答案2

有一些方法可以避免execute在节点上运行多次:

  • 使用not_if,only_if语句。
  • 使用action :nothing然后通知此execute资源从另一个资源运行。(仅当您每次需要在第一个资源更改时运行它时)
  • 使用creates [some/file](Chef 将运行它,仅当文件不存在时,相当于not_if { ::File.exists? '[some/file]' }

如果您无法轻松确定脚本是否在不创建附加文件的情​​况下运行,那么这是唯一的方法。所以,实际上,您做的一切都是正确的。

除非你提供的代码能够真正运行,如果文件存在。但我想那是一个打字错误。

相关内容