如何让厨师在运行其他食谱之前运行apt-get update

现在我在我的Vagrantfile中有以下内容:

config.vm.provision :chef_solo do |chef| chef.cookbooks_path = "cookbooks" chef.add_recipe "apt" chef.add_recipe "build-essential" chef.add_recipe "chef-redis::source" chef.add_recipe "openssl" chef.add_recipe "git" chef.add_recipe "postgresql::server" chef.add_recipe "postgresql::client" end 

为了安装添加到我的recipe_list的软件,我需要在安装其他软件之前让VM发出apt-get更新

我的印象是,这是“合适”配方的特点之一 – 它会运行更新的第一件事情。

当我做一个stream浪汉的规定是:

 [Sat, 11 Feb 2012 22:20:03 -0800] INFO: *** Chef 0.10.2 *** [Sat, 11 Feb 2012 22:20:03 -0800] INFO: Setting the run_list to ["recipe[apt]", "recipe[build-essential]", "recipe[chef-redis::source]", "recipe[openssl]", "recipe[git]", "recipe[postgresql::server]", "recipe[postgresql::client]", "recipe[vagrant-main]"] from JSON [Sat, 11 Feb 2012 22:20:03 -0800] INFO: Run List is [recipe[apt], recipe[build-essential], recipe[chef-redis::source], recipe[openssl], recipe[git], recipe[postgresql::server], recipe[postgresql::client], recipe[vagrant-main]] [Sat, 11 Feb 2012 22:20:03 -0800] INFO: Run List expands to [apt, build-essential, chef-redis::source, openssl, git, postgresql::server, postgresql::client, vagrant-main] [Sat, 11 Feb 2012 22:20:03 -0800] INFO: Starting Chef Run for lucid32 [Sat, 11 Feb 2012 22:20:03 -0800] INFO: Processing package[postgresql-client] action install (postgresql::client line 37) [Sat, 11 Feb 2012 22:20:04 -0800] ERROR: package[postgresql-client] (postgresql::client line 37) has had an error [Sat, 11 Feb 2012 22:20:04 -0800] ERROR: Running exception handlers [Sat, 11 Feb 2012 22:20:04 -0800] ERROR: Exception handlers complete [Sat, 11 Feb 2012 22:20:04 -0800] FATAL: Stacktrace dumped to /tmp/vagrant-chef-1/chef-stacktrace.out [Sat, 11 Feb 2012 22:20:04 -0800] FATAL: Chef::Exceptions::Exec: package[postgresql-client] (postgresql::client line 37) had an error: apt-get -q -y install postgresql-client=8.4.8-0ubuntu0.10.04 returned 100, expected 0 

您可以在开始时包括适当的配方:

 include_recipe 'apt' 

这将运行更新命令。

apt-get update应该先按照你的方式运行。 但是,配方只会每24小时更新一次:

 execute "apt-get-update-periodic" do command "apt-get update" ignore_failure true only_if do File.exists?('/var/lib/apt/periodic/update-success-stamp') && File.mtime('/var/lib/apt/periodic/update-success-stamp') < Time.now - 86400 end end 

有三个资源可以在Ubuntu系统上很好的完成这个任务,特别是在12.04精确的64位上。

  1. 当其他食谱需要时,随意运行apt-get-update

  2. 安装update-notifier-common软件包,为我们提供更新时间戳

  3. 检查时间戳并定期更新。 在这种情况下86400秒以下。

这是三个食谱。

 execute "apt-get-update" do command "apt-get update" ignore_failure true action :nothing end package "update-notifier-common" do notifies :run, resources(:execute => "apt-get-update"), :immediately end execute "apt-get-update-periodic" do command "apt-get update" ignore_failure true only_if do File.exists?('/var/lib/apt/periodic/update-success-stamp') && File.mtime('/var/lib/apt/periodic/update-success-stamp') < Time.now - 86400 end end 

它看起来像opscode apt cookbook的最新版本允许您在编译时运行它。

 config.vm.provision :chef_solo do |chef| chef.cookbooks_path = "cookbooks" chef.add_recipe "apt" chef.json = { "apt" => {"compiletime" => true} } end 

只要apt在运行列表中的其他编译时间食谱(如postgres)之前运行,这应该工作。

我似乎已经能够通过应用以下补丁来解决问题:

https://github.com/wil/cookbooks/commit/a470a4f68602ec3bf3374830f4990a7e19e9de81

这里发布的其他答案很可能会导致关于资源克隆的警告。

根据Apt的cookbook文档 ,你应该可以通过设置node['apt']['compile_time_update'] = true来实现这一点,但是我自己从来没有用过这种方法

这是我所做的:

这将加载原始apt-get update资源,并确保它运行时不会向资源集合添加重复条目。 这将导致在编译阶段每个Chef运行期间执行apt-get update

 # First include the apt::default recipe (so that `apt-get update` is added to the collection) include_recipe 'apt' # Then load the `apt-get update` resource from the collection and run it resources(execute: 'apt-get update').run_action(:run) 

显然,你也想在apt.rb文件中包含apt Cookbook:

 # ./metadata.rb depends 'apt' 

解决问题的最简单和最直接的方法是应用以下补丁(h / t @ashchristopher):

https://github.com/wil/cookbooks/commit/a470a4f68602ec3bf3374830f4990a7e19e9de81

问题是postgresql::client配方在编译时在postgresql / recipes / client.rb:39和44上的包资源上运行安装操作,而不像正常(h / t Tim Potter)那样运行,导致在任何事情发生之前,他们都要由厨师进行评估。

 pg_packages.each do |pg_pack| package pg_pack do action :nothing end.run_action(:install) end gem_package "pg" do action :nothing end.run_action(:install) 

我相信这是通过服务于database食谱的postgres提供者来完成的,这个提供者依赖于postgresql食谱,并且依赖于在编译前安装的pg gem。 应用上述补丁可能会破坏database食谱。

另一种方法是创build一个在编译时运行apt-get update的配方,并把它放在postgresql食谱之前的run_list 。 最简单的forms可能是这样的:

 execute "apt-get update" do action :nothing end.run_action(:install) 

没有修补,这是一个通用的方法来解决每次运行都会更新的问题:

 bash "update-apt-repository" do user "root" code <<-EOH apt-get update EOH end 

可能值得考虑的是,在每一次运行中,这样的运行都会占用大约30秒的系统资源。 你可能想要一个名为recipe :: update_apt的特殊配方,你已经通过cron或者通过一些其他的事件来运行

 chef-client -o "recipe[yourrecipe::update_apt]" 

要在编译时运行apt-get update,请执行以下操作:

 e = execute "apt-get update" do action :nothing end e.run_action(:run) 

检查https://wiki.opscode.com/display/chef/Evaluate+and+Run+Resources+at+Compile+Time

我也有同样的情况,在我的情况下,在烹调包装的安装后,第二次。 只要把它留在这里,也许有人会从中受益。 检查您的运行列表,angular色或其他地方的食谱的顺序。

只是一个友好的提醒,添加所有这些stream浪食品内的食谱可以很快变得难以pipe理。

一个更好的模式是创build一个厨师angular色chef/my-fancy-role.rb

 # Name of the role should match the name of the file name "my-fancy-role" # Run list function we mentioned earlier run_list( "recipe[apt]", "recipe[build-essential]", "recipe[chef-redis::source]", "recipe[openssl]" ) 

然后将这个angular色添加到Vagrantfileconfiguration部分:

 config.vm.provision :chef_solo do |chef| chef.roles_path = "chef/roles" chef.cookbooks_path = ["chef/site-cookbooks", "chef/cookbooks"] chef.add_role "my-fancy-role" end