Chef中script资源执行无效但execute正常的问题排查求助
问题分析与解决方案:Chef script资源卸载RPM包无效,execute资源正常
问题重现
最初使用script资源编写卸载TrendMicro相关RPM包的Recipe:
script 'uninstall trendmicro package' do interpreter 'bash' user 'root' code <<-BASH rpm -qa|grep "ds_agent\|trend"|xargs -I{} rpm -e {} BASH only_if 'rpm -q ds_agent' end
执行chef-client -z -o"recipe[ccloud_av_trendmicro::uninstall_tm]"后,日志显示script已执行,但目标RPM包仍存在:
vsa10121641:/tmp/cookbooks # chef-client -z -o "recipe[ccloud_av_trendmicro::uninstall_tm]" [2022-07-27T08:27:32+00:00] WARN: No config file found or specified on command line, using command line options. Starting Chef Client, version 12.19.36 [2022-07-27T08:27:33+00:00] WARN: Run List override has been provided. [2022-07-27T08:27:33+00:00] WARN: Original Run List: [] [2022-07-27T08:27:33+00:00] WARN: Overridden Run List: [recipe[ccloud_av_trendmicro::uninstall_tm]] resolving cookbooks for run list: ["ccloud_av_trendmicro::uninstall_tm"] Synchronizing Cookbooks: - ccloud_av_trendmicro (0.0.10) Installing Cookbook Gems: Compiling Cookbooks... Converging 1 resources Recipe: ccloud_av_trendmicro::uninstall_tm * script[uninstall trendmicro package] action run - execute "bash" "/tmp/chef-script20220727-20794-ewbo7s" [2022-07-27T08:27:34+00:00] WARN: Skipping final node save because override_runlist was given Running handlers: Running handlers complete Chef Client finished, 1/1 resources updated in 02 seconds vsa10121641:/tmp/cookbooks # rpm -qa|grep "ds_agent\|trend" trendmicro-updater-1.4268-1.2.SAP.noarch ds_agent-9.6.2-8140.x86_64 byd-trendmicro-check-1.4859-1.2.SAP.noarch
将资源替换为execute后,卸载成功:
execute 'uninstall trendmicro package' do command 'rpm -qa|grep "ds_agent\|trend"|xargs -I{} rpm -e {}' only_if 'rpm -q ds_agent' end
执行后目标包被完全清除:
vsa10121641:/tmp/cookbooks # chef-client -z -o "recipe[ccloud_av_trendmicro::uninstall_tm]" [2022-07-27T08:32:50+00:00] WARN: No config file found or specified on command line, using command line options. Starting Chef Client, version 12.19.36 [2022-07-27T08:32:52+00:00] WARN: Run List override has been provided. [2022-07-27T08:32:52+00:00] WARN: Original Run List: [] [2022-07-27T08:32:52+00:00] WARN: Overridden Run List: [recipe[ccloud_av_trendmicro::uninstall_tm]] resolving cookbooks for run list: ["ccloud_av_trendmicro::uninstall_tm"] Synchronizing Cookbooks: - ccloud_av_trendmicro (0.0.10) Installing Cookbook Gems: Compiling Cookbooks... Converging 1 resources Recipe: ccloud_av_trendmicro::uninstall_tm * execute[uninstall trendmicro package] action run - execute rpm -qa|grep "ds_agent\|trend"|xargs -I{} rpm -e {} [2022-07-27T08:32:53+00:00] WARN: Skipping final node save because override_runlist was given Running handlers: Running handlers complete Chef Client finished, 1/1 resources updated in 02 seconds vsa10121641:/tmp/cookbooks # rpm -qa|grep "ds_agent\|trend"
原因分析
- 执行环境差异:
script资源会把代码写入临时脚本文件再执行,而execute资源直接在当前shell环境运行命令。当用xargs结合rpm -e时,临时脚本的环境可能缺失关键变量(比如PATH),导致rpm命令执行异常但无明显报错。- 即便设置了
user 'root',临时脚本的执行权限、上下文和execute直接以root身份运行仍有细微差别,部分RPM包卸载需要特定环境上下文才能完成。
- 错误捕获逻辑不同:
script资源默认不会因脚本内的命令失败终止执行(除非显式设置returns参数),如果某个rpm -e失败(比如依赖问题),后续命令可能中断但日志无提示;而execute会默认捕获退出码,执行失败会在日志中体现。
解决方案
方案1:修复script资源执行问题
如果坚持用script资源,可做以下调整:
- 显式指定
rpm绝对路径,避免PATH缺失导致命令找不到:
script 'uninstall trendmicro package' do interpreter 'bash' user 'root' code <<-BASH /usr/bin/rpm -qa|grep "ds_agent\|trend"|xargs -I{} /usr/bin/rpm -e {} BASH only_if '/usr/bin/rpm -q ds_agent' end
- 添加日志和错误捕获,方便排查:
script 'uninstall trendmicro package' do interpreter 'bash' user 'root' code <<-BASH set -euo pipefail echo "Starting RPM uninstall..." >> /tmp/tm_uninstall.log PACKAGES=$(/usr/bin/rpm -qa|grep "ds_agent\|trend") echo "Found packages: $PACKAGES" >> /tmp/tm_uninstall.log for pkg in $PACKAGES; do echo "Uninstalling $pkg..." >> /tmp/tm_uninstall.log /usr/bin/rpm -e "$pkg" >> /tmp/tm_uninstall.log 2>&1 if [ $? -ne 0 ]; then echo "Failed to uninstall $pkg" >> /tmp/tm_uninstall.log fi done BASH only_if '/usr/bin/rpm -q ds_agent' end
方案2:使用execute资源(推荐)
execute资源更适合单条或简单管道命令,执行上下文更直接,避免临时脚本的环境问题,正如测试结果,直接使用即可正常卸载。
更规范的Chef做法是用rpm_package资源,符合Chef资源模型,更好处理依赖和状态跟踪:
# 获取所有需要卸载的包 packages = shell_out!('/usr/bin/rpm -qa | grep "ds_agent\|trend"').stdout.split packages.each do |pkg| rpm_package pkg do action :remove end end
内容的提问来源于stack exchange,提问作者EisenWang
相关产品推荐
相关产品推荐

