【问题标题】:Chef compile error when capturing shell output捕获 shell 输出时 Chef 编译错误
【发布时间】:2019-01-13 23:58:58
【问题描述】:

我有一个看起来像这样的厨师食谱:

package 'build-essential' do
  action :install
end

cmd = Mixlib::ShellOut.new("gcc -dumpversion")
cmd.run_command
gcc_version = cmd.stdout.strip()

如果我在安装了 gcc 的系统上执行配方,配方运行良好,没有错误。但是,如果我在没有安装 gcc 的系统上运行配方,我会收到错误消息“没有这样的文件或目录 - gcc”。

当我试图找到解决我的问题的方法时,我开始了解厨师两阶段的东西。我期待软件包安装能够满足 gcc 要求。我如何告诉厨师这个要求稍后会得到满足并且不会在编译时抛出错误?

我尝试了以下,但属性没有得到更新。

Chef::Resource::RubyBlock.send(:include, Chef::Mixin::ShellOut)
ruby_block "gcc_version" do
  block do
    s = shell_out("gcc -dumpversion")
    node.default['gcc_version'] = s.stdout.strip()
  end
end

echo "echo #{node[:gcc_version]}" do
  command "echo #{node[:gcc_version]}"
end

感谢任何帮助。谢谢。

【问题讨论】:

    标签: shell compiler-errors output chef-infra lazy-evaluation


    【解决方案1】:

    好吧,这里有几个问题。首先,忘记Chef::Resource::whatever.send(:include 的把戏。永远不要这样做,从字面上看永远不会。在这种情况下,无论如何,ShellOut mixin 已经在所有地方都可用。

    接下来,更重要的是,您仍然遇到了两次混淆问题。有关详细信息,请参阅 https://coderanger.net/two-pass/,但基本上是 echo 资源中的字符串(我假设最初是说 execute 并且您搞砸了应对?)在编译时被插值。您还没有说您要做什么,但您可能需要使用 lazy{} 辅助方法。

    最后,不要将东西存储在这样的节点属性中,它非常脆弱且难以处理。

    【讨论】:

    • 谢谢。基本上,尝试获取已安装的 gcc 版本。我正在我的食谱中编译和安装一个库。但是,库安装路径包括编译器版本。例如,安装路径可以是 '/usr/local/lib/libname/{gcc-ver}/abc。在我的食谱中,我需要访问此路径。除 gcc 版本外,其余路径是静态的。我正在尝试将版本放入本地 var。构建路径。 build-essential pkg 将安装 gcc。如果我的 cmd 在安装后运行,它会找到 gcc。但是,我的 cmd 在编译时运行,即在 gcc 安装之前。
    • 反过来,选择您想要的版本并将其放入您的配方代码中:)
    • 不知道我该怎么做。我不知道先验版本。这取决于机器。我正在寻找一种方法来告诉厨师在编译期间不要评估 shell 表达式。
    • 你通过强迫它知道它:package 'gcc' do version 'whatever' end :)
    • 我不能强迫它,因为这个配方必须适用于不同的操作系统发行版,而且每个发行版都有不同的版本,我不能将它们限制为特定的版本。有没有其他方法可以告诉厨师在编译时忽略 shell 命令评估?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-23
    • 1970-01-01
    • 2012-08-29
    • 1970-01-01
    相关资源
    最近更新 更多