Chef配置:首次运行时Bash块按依赖执行并加锁校验
嘿,先给你点个赞,你用notify来控制bash块的顺序执行思路是对的,但手动用Ruby的File.exist?做判断其实有点违背Chef的声明式设计,而且代码也可以更简洁可靠。我来给你梳理下更优的实现方式:
核心优化思路
Chef本身就是为声明式配置管理设计的,我们可以利用它的原生资源属性和依赖系统来替代手动的锁文件判断,既减少冗余代码,又能保证执行逻辑的可靠性:
用
creates属性替代手动锁文件判断bash资源的creates属性可以指定一个文件路径,Chef会自动检查这个文件是否存在:如果不存在,就执行该bash块;如果已经存在,就跳过。这完全可以替代你手动写的if not File.exist?判断,而且是Chef收敛阶段自动评估的,更符合其设计逻辑。将锁文件创建与bash块强绑定
把锁文件的file资源设置为:nothing动作,只有当对应的bash块执行完成后,通过notifies触发创建锁文件。这样锁文件的生成和bash块的执行状态完全绑定,避免手动判断可能出现的不一致。用
notifies/subscribes管理依赖顺序
继续保留你用notify实现的顺序依赖,但可以结合subscribes让后续bash块主动订阅前一个块的执行事件,逻辑更清晰。
优化后的代码示例
首先定义锁文件路径(建议放在一个统一的位置,比如/var/run/tableau下):
tsm_login_lock = '/var/run/tableau/tsm_login.lock' tsm_init_lock = '/var/run/tableau/tsm_init.lock'
然后是第一个bash块和对应的锁文件:
bash 'login_tsm' do user tableau_user cwd tableau_user_home code <<-EOH source /etc/profile.d/tableau_server.sh tsm login -u #{tableau_user} -p #{password} tsm settings import -f /home/analytics/setting_file.json tsm pending-changes apply tsm licenses activate -k #{key} tsm register --file #{registration} tsm pending-changes apply EOH creates tsm_login_lock # 锁文件不存在时才执行该bash块 notifies :create, "file[#{tsm_login_lock}]", :immediately notifies :run, "bash[tsm_init]", :immediately end file tsm_login_lock do mode '0644' content 'tableau server login and config completed' action :nothing # 默认不执行,只有被notify才创建 end
接下来是第二个bash块,这里可以用subscribes主动订阅前一个bash块的执行,同时用creates控制重复执行:
bash 'tsm_init' do user tableau_user cwd tableau_user_home code <<-EOH tsm initialize --start-server --request-timeout 1800 EOH creates tsm_init_lock subscribes :run, "bash[login_tsm]", :immediately # 当login_tsm执行时,立即运行这个块 notifies :create, "file[#{tsm_init_lock}]", :immediately end file tsm_init_lock do mode '0644' content 'tableau server initialized' action :nothing end
进阶优化:基于真实状态判断(而非仅锁文件)
如果担心锁文件被误删导致重复执行,还可以结合only_if/not_if用真实的服务状态来判断,比如检查TSM是否已经初始化:
bash 'tsm_init' do # ... 其他属性 only_if do # 执行tsm status命令,判断服务是否未运行/未初始化 !shell_out('tsm status').success? end end
这样即使锁文件丢失,Chef也会根据实际的服务状态决定是否执行初始化,逻辑更健壮。
总结
相比你手动写的Ruby条件判断,用Chef原生的creates、notifies、only_if等特性来实现,代码更简洁,逻辑更符合声明式配置的思想,而且Chef会自动处理资源的执行顺序和状态校验,可靠性更高。
内容的提问来源于stack exchange,提问作者user9753902

