Chef cookbook中识别动态变量后如何为所有配方统一设置该变量
Chef多配方共享Tomcat安装路径的实现方案
以下是3种可直接落地的实现方式,可根据你的实际场景选择:
方案1:持久化存储到节点normal级别属性
该方案会将识别到的路径持久化存储到节点对象中,后续Chef运行时即使不重新执行发现逻辑也能直接读取,适合路径长期固定的场景。
- 首先修正默认属性的错误写法:你当前的属性值被包裹了额外的双引号,实际应为数组类型:
# attributes/default.rb default['tomcat_cookbook']['tomcathome'] = ['/home/tomcat', '/home/ApacheTomcat']
- 在首个路径发现配方中实现路径识别与属性赋值:
# 路径发现配方中的逻辑 real_tomcathome = node['tomcat_cookbook']['tomcathome'].find do |path| File.directory?(path) end # 异常处理:找不到路径时直接抛出明确错误 unless real_tomcathome raise "未在服务器上找到有效Tomcat安装路径,请检查候选路径配置" end # 赋值为normal级别属性,会持久化到节点对象,优先级高于default node.normal['tomcat_cookbook']['real_tomcathome'] = real_tomcathome
- 后续所有启停配方直接调用该属性即可:
# 停止Tomcat示例 execute "stop_tomcat" do command "#{node['tomcat_cookbook']['real_tomcathome']}/bin/shutdown.sh" user "tomcat" end
方案2:封装为公共库函数
该方案将路径识别逻辑统一抽离到公共库,所有配方调用同一个方法获取路径,无需重复编写判断逻辑,适合需要每次运行都动态校验路径的场景。
- 在cookbook下新建
libraries/tomcat_helper.rb文件,写入公共方法:
module TomcatCookbook module Helper def get_real_tomcathome possible_paths = node['tomcat_cookbook']['tomcathome'] real_path = possible_paths.find { |path| File.directory?(path) } unless real_path raise "未找到有效Tomcat安装路径" end real_path end end end # 将方法注入到Chef配方的DSL中 Chef::Recipe.include(TomcatCookbook::Helper)
- 所有配方直接调用方法即可,无需重复写判断逻辑:
# 启动Tomcat示例 execute "start_tomcat" do command "#{get_real_tomcathome}/bin/startup.sh" user "tomcat" end
方案3:存储到运行时临时变量run_state
该方案不会把路径持久化到节点对象,仅在本次Chef运行期间生效,适合不希望节点属性存储额外数据的场景。
- 在路径发现配方中写入run_state:
real_tomcathome = node['tomcat_cookbook']['tomcathome'].find { |path| File.directory?(path) } node.run_state['real_tomcathome'] = real_tomcathome
- 后续配方直接读取run_state即可:
tomcat_home = node.run_state['real_tomcathome']
注意事项
- 若选择方案1或3,需确保路径发现配方在run_list中的顺序排在所有Tomcat启停配方之前
- 建议所有场景都添加路径不存在的异常处理,避免后续执行出现无意义的报错
内容的提问来源于stack exchange,提问作者Mayur
相关产品推荐
相关产品推荐

