Chef中return代码块失效求助:ffmpeg已安装时未终止Recipe
Hey there! Let's break down exactly why your recipe's check is being ignored, and fix it step by step.
First: The Ruby Syntax Problem in Your First Code Snippet
Your initial recipe code has a syntax error that's causing Chef to skip the entire logic block entirely. Let's look at what you wrote:
ohai 'reload' do action :reload end if node['packages'].keys.include?('ffmpeg') return end
This is invalid Ruby syntax—you're trying to cram an if condition, a resource definition, and a return statement into one line in a way Ruby can't parse. The interpreter gets confused and just skips the whole thing. A corrected version would separate the logic clearly:
# First check if ffmpeg is installed if node['packages'].key?('ffmpeg') return end # Then reload Ohai if needed (though we'll talk about why this order might be wrong next) ohai 'reload' do action :reload end
Second: Chef's Compile vs Converge Phase Confusion
Even your second, syntactically correct snippet (return if node['packages'].keys.include?('ffmpeg')) might not work as expected, and this is due to how Chef runs recipes:
- Compile Phase: Chef first parses all your recipe code, collects all resources to run, and evaluates any Ruby code that isn't part of a resource block. At this point,
node['packages']uses the Ohai data collected at the very start of the Chef run. - Converge Phase: Chef executes all the resources it collected during the compile phase (like your
ohai 'reload'resource).
The problem? Your return statement runs during the compile phase, but the ohai 'reload' resource only runs later in the converge phase. So you're checking outdated package data before Ohai has a chance to refresh it.
Fixing the Phase Issue
To check the real-time state of installed packages, you need to manually refresh Ohai's packages data during the compile phase (not using a resource). Here's how to do that:
# Manually reload Ohai's packages plugin in the compile phase Ohai::System.new.tap do |ohai| ohai.load_plugin('packages') ohai.run_plugins(['packages']) # Update the node's automatic attributes with fresh package data node.automatic_attrs['packages'] = ohai.data['packages'] end # Now check the fresh package data and exit if ffmpeg is present return if node['packages'].key?('ffmpeg')
Third: Chef Zero's Quirk with Node Data
When using Chef Zero (chef-client -z), it stores node data locally in the .chef/nodes directory. If you installed ffmpeg after your first Chef run, Chef Zero will reuse the old node data (with outdated package info) unless you:
- Delete the old node file from
.chef/nodes, or - Use the manual Ohai reload method above to force fresh data collection each run.
Answering Your Final Questions
- Is this a Ruby basics issue? Your first snippet does have a Ruby syntax error, but the core problem with your second snippet is Chef's unique compile/converge phase model—this is Chef-specific knowledge, not just Ruby basics.
- Why does Chef assume prior knowledge? Chef is built on Ruby, so it does expect some familiarity with the language, but the phase model is a common pain point for new users. It's less about assuming expertise and more about how Chef's architecture works, which can be tricky to pick up at first.
内容的提问来源于stack exchange,提问作者Adhitya Ganesan

