Prevent chef recipe from executing previously executed action?

This is generally the method I use, especially if the command you take results in a file being created as a side effect For example disabling or enabling sites in Debian's apache2 package removes or creates links in /etc/apache2 which you can test for using File.exists?.

A trick is to set an attribute after the execute resource has run:

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

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

Note that it's still possible for the execute resource to be run twice in some situations so this technique isn't perfect, but you can now use knife-search to determine which nodes have performed the execute.


There are some ways to keep execute from running several times on node:

  • Using not_if, only_if statements.
  • Using action :nothing and then notifying this execute resource to run from another resource. (only if you need to run it every time the first resource changes)
  • Using creates [some/file] (Chef will run it, only if the file does not exist, equivalent to not_if { ::File.exists? '[some/file]' }

If you cannot easily determine, if your script has run without creating an additional file, then it is the only way. So you, actually, are doing everything right.

Except that the code you provided will actually run, if the file exists. But I suppose that is a typo.