Chef食谱编译错误:undefined method 'cwd' for cookbook 求助
问题诊断与修正方案
核心问题分析
编译错误
undefined method 'cwd' for cookbook
该错误通常由以下原因导致:- Chef客户端版本过低(建议使用Chef 12+版本,早期版本对
execute资源的cwd属性支持不完善); - 食谱代码缩进不规范,导致
execute资源块语法非法; - 角色未正确应用到节点,导致节点属性未加载。
- Chef客户端版本过低(建议使用Chef 12+版本,早期版本对
脚本无法运行的关键原因
你设置的devops_dir是本地工作站的cookbook路径,但Chef客户端在目标EC2节点运行时,cookbook会被下载到节点的缓存目录(默认路径为/var/chef/cache/cookbooks/),而非你指定的本地路径,导致cwd指向的目录不存在,脚本无法被找到。节点变量迭代有效性
节点变量完全可以在数组迭代中生效,你对employees数组的遍历逻辑本身是正确的。
修正后的食谱方案
方案一:标准做法(推荐)
使用cookbook_file将脚本同步到目标节点,避免路径依赖:
- 在
hello-chefcookbook中创建files/default/scripts目录,将shell.sh放入该目录; - 修改
multi-module.rb食谱:
node['employees'].each do |employee| # 同步脚本到节点指定目录 cookbook_file "/tmp/scripts/shell.sh" do source "scripts/shell.sh" owner node['user'] group node['group'] mode '0755' action :create not_if { ::File.exist?("/tmp/scripts/shell.sh") } end execute "test-multi-#{employee['name']}" do cwd "/tmp/scripts" user node['user'] group node['group'] # 使用数组形式避免命令注入风险 command ["bash", "shell.sh", employee['name'], employee['email']] end end
方案二:使用节点缓存路径(不推荐)
若需直接使用cookbook中的脚本,可通过Chef内置变量获取节点上的缓存路径:
node['employees'].each do |employee| execute "test-multi-#{employee['name']}" do cwd "#{Chef::Config[:file_cache_path]}/cookbooks/#{cookbook_name}/recipes/scripts" user node['user'] group node['group'] command ["bash", "shell.sh", employee['name'], employee['email']] end end
验证步骤
- 确认角色已应用到节点:运行
knife node show <节点名称> -r,检查run_list是否包含recipe[multi-module]; - 上传更新后的cookbook:
knife cookbook upload hello-chef; - 在节点执行Chef客户端:
sudo chef-client; - 查看执行日志:
/var/log/chef/client.log,确认脚本执行状态。
内容的提问来源于stack exchange,提问作者Shyam
相关产品推荐
相关产品推荐

