Puppet:仅当文件不存在时执行命令的配置问题求助
解决Puppet仅在文件不存在时执行资源的问题
你的核心问题在于对Puppet require 元参数的逻辑理解有误。require => Exec['is_file_there'] 只是确保Puppet先评估这个exec资源,但不管exec是执行成功还是被跳过,后续的依赖资源都会被正常评估和执行——这就是为什么你的file资源不管/tmp/some_file是否存在都会被创建的原因。
下面针对你的需求(后续资源不支持onlyif参数)提供两种可行方案:
方案1:用notify + refreshonly 实现条件触发
这是最适合你场景的方案,不需要后续资源支持onlyif,只需要它支持refreshonly(绝大多数Puppet内置资源和自定义资源都支持这个参数):
# 当/tmp/some_file不存在时,执行这个exec并发送刷新信号 exec {"check_some_file_absence": command => "true", path => ["/usr/bin","/usr/sbin","/bin"], unless => "test -e /tmp/some_file", notify => File['/tmp/success'], # 执行时通知后续资源 } # 只有收到exec的刷新信号时才执行 file {'/tmp/success': ensure => present, refreshonly => true, # 关键:仅在被触发刷新时运行 }
逻辑说明
- 当
/tmp/some_file不存在时,exec的unless条件成立(test -e返回非0),exec会执行true,并向File['/tmp/success']发送刷新信号,此时file资源会创建文件。 - 当
/tmp/some_file存在时,exec的unless条件不成立,exec被跳过,不会发送刷新信号,file资源也会被跳过,完全符合你的需求。
方案2:用Puppet条件语句直接声明资源
如果后续资源连refreshonly都不支持,你可以直接用Puppet的条件判断来决定是否声明该资源:
# 检查/tmp/some_file是否不存在 if ! test('e', '/tmp/some_file') { file {'/tmp/success': ensure => present, } # 这里可以添加其他需要在文件不存在时执行的资源 somecommand { 'my_custom_task': ... # 你的资源参数 } }
逻辑说明
test('e', '/path')是Puppet内置函数,用于检查文件是否存在(返回布尔值)。- 只有当文件不存在时,条件块内的所有资源才会被Puppet评估和执行,否则直接跳过整个块。
原写法失效的原因
再回头解释下你原配置的问题:
你的exec资源在文件存在时会被标记为skipped(跳过执行),但Puppet的require元参数只关心依赖资源是否被评估过,而不是是否被执行过。所以即使exec被跳过,后续的file资源依然会被执行,这就导致了不符合预期的结果。
内容的提问来源于stack exchange,提问作者user1074593
相关产品推荐
相关产品推荐

