如何检查Chef中是否存在文件夹?
这是我的代码:
if !::File.exist?("#{node['iis']['home']}\\backup\\BkpB4Chef") windows_batch "Backup IIS Config" do code <<-EOH "#{node['iis']['home']}"\\appcmd add backup BkpB4Chef EOH end end
它总是说文件存在并执行循环。
你应该在这里使用厨师守卫 。 Guards指定条件执行,但仍将资源插入资源集合中。 在您的示例和jtblin回答中,资源永远不会添加到集合中(稍后我将进一步解释)。
这里有一些工作代码可以帮助您入门:
windows_batch "Backup IIS Config" do code %Q|#{node['iis']['home']}"\\appcmd add backup BkpB4Chef| not_if { ::File.directory?("#{node['iis']['home']}\\backup\\BkpB4Chef") } end
使用creates
许多非幂等Chef资源也支持creates
参数,该参数解释了资源的作用。 换句话说, windows_batch
“创建”了什么。 这可以是文件,目录或可执行文件。 因此,以下代码等同于前一个答案。
windows_batch "Backup IIS Config" do code %Q|#{node['iis']['home']}"\\appcmd add backup BkpB4Chef| creates"#{node['iis']['home']}\\backup\\BkpB4Chef" end
为什么not_if
vs条件包装器
Chef分两个阶段执行 – 编译阶段和收敛阶段。 在编译阶段,将对配方进行规避,并将资源添加到资源集合中。 在收敛阶段,资源集合中的资源将针对目标系统执行和评估。 因此,请考虑以下示例:
if false service 'foo' do action :start end end
这是一个相当简单的配方,它基于某些条件启动服务。 但是,在编译阶段结束时, service
资源不会添加到资源集合中。 由于配方DSL是instance_eval
ed,因此包装if false
条件会阻止Ruby VM读取该代码。 换句话说,就像服务永远不存在一样。
通知资源是相当普遍的。 在配方的后面,您可能希望因配置更改而重新启动apache。 “正确”的方法是使用通知:
template '/var/www/conf.d/my.conf.file' do # ... notifies :restart, 'service[apache2]' end
此template
无法充分通知服务资源,因为它在资源集合中不存在。 所以这个配方会失败。 这似乎是一个简单的例子,但是如果你将条件if false
if更改为节点属性test:
if node['cookbook']['use_apache'] service 'apache2' do action :start end end
你已经在你的食谱中创造了一个二分法,它可以在50%的时间里起作用。 不幸的是,大多数烹饪书比两个资源复杂得多,因此资源可以通知不存在的资源的边缘情况的数量急剧增加。 这是使用资源保护所有可解决的(并表现出正确的行为):
service 'apache2' do action :start only_if { node['cookbook']['use_apache'] } end
使用Dir.exists?
。 您也可以替换if ! condition
if ! condition
, unless condition
读得更好。
unless Dir.exist? "#{node['iis']['home']}\\backup\\BkpB4Chef" windows_batch "Backup IIS Config" do code <<-EOH "#{node['iis']['home']}"\\appcmd add backup BkpB4Chef EOH end end