• Uncategorized

About linux : Chef-Multi-line-command

Question Detail

I’m trying to write a recipe in Chef but I’m stuck on how I can do a multi line execute into command line in Linux. Firstly is the recipe and following that is the error output I receive.

node['freeswitch']['source']['dependencies'].each { |d| package d }

execute "apt_update" do
  command "wget -O - https://files.freeswitch.org/repo/deb/debian/freeswitch_archive_g0.pub | apt-key add -&&"
    "echo "deb http://files.freeswitch.org/repo/deb/freeswitch-1.6/ jessie main" > /etc/apt/sources.list.d/freeswitch.list &&"
    "apt-get update &&"
    "apt-get install -y --force-yes freeswitch-video-deps-most &&"

    # because we're in a branch that will go through many rebases it's
    # better to set this one, or you'll get CONFLICTS when pulling (update)
    git config --global pull.rebase true

Below is the error output

No resource or method named `command' for `Chef::Recipe "source"'

Cookbook Trace:
/var/chef/cache/cookbooks/freeswitch/recipes/source.rb:6:in `from_file'
/var/chef/cache/cookbooks/freeswitch/recipes/default.rb:5:in `from_file'
Relevant File Content:

1:  #include_recipe 'apt'
3:  node['freeswitch']['source']['dependencies'].each { |d| package d }
5:  execute "apt_update"
6>> command 'wget -O - https://files.freeswitch.org/repo/deb/debian/freeswitch_archive_g0.pub | apt-key add -'&&
7:    'echo "deb http://files.freeswitch.org/repo/deb/freeswitch-1.6/ jessie main" > /etc/apt/sources.list.d/freeswitch.list' &&
8:          'apt-get update' &&
9:          'apt-get install -y --force-yes freeswitch-video-deps-most' &&
11:  # because we're in a branch that will go through many rebases it's
12:  # better to set this one, or you'll get CONFLICTS when pulling (update)
13:          'git config --global pull.rebase true'
15:  execute "git_clone" do


Running handlers:
[2016-08-02T09:19:35+01:00] ERROR: Running exception handlers
Running handlers complete
[2016-08-02T09:19:35+01:00] ERROR: Exception handlers complete
Chef Client failed. 0 resources updated in 01 seconds
[2016-08-02T09:19:35+01:00] FATAL: Stacktrace dumped to /var/chef/cache/chef-stacktrace.out
[2016-08-02T09:19:35+01:00] FATAL: Please provide the contents of the stacktrace.out file if you file a bug report
[2016-08-02T09:19:35+01:00] ERROR: No resource or method named `command' for `Chef::Recipe "source"'
[2016-08-02T09:19:35+01:00] FATAL: Chef::Exceptions::ChildConvergeError: Chef run process exited unsuccessfully (exit code 1)

Question Answer

The && is the logical and operator of a shell. Either you explicitly start the command in a shell, like:

execute 'Execute a shell' do
    command "bash -c 'cmd1 && cmd2 && ..'"

or you use the bash resource:

bash 'Execute bash script' do
    code <<-EOH
    cmd1 \
    && cmd2 \
    && ... 

As I don’t want to down-vote both question and the only answer without showing you how to do it (at least a bit more) right, here you are. Your code writing monkey created a recipe that adds the apt repo and installs the package:

# recipes/default.rb

# the package resource can handle multiple packages at once
package node['freeswitch']['source']['dependencies']

# set up a new apt repo, import the key, automatically triggers `apt-get update`
apt_repository "freeswitch" do
  key "https://files.freeswitch.org/repo/deb/debian/freeswitch_archive_g0.pub"
  uri "http://files.freeswitch.org/repo/deb/freeswitch-1.6/"
  components ['main']
  distribution node['lsb']['codename']

# finally, install this package. You could even merge the first line with this one.
package "freeswitch-video-deps-most"

You just have to declare the apt cookbook as a dependency in your metadata.rb:

# metadata.rb
name 'whatever'

depends "apt"

It’s really easy, when you get a bit used to it. Bonus: it’s idempotent.

  1. Using ‘bash’ resource

    bash 'install' do
      user 'root'
      cwd "#{Chef::Config['file_cache_path']}/temp"
      code <<-EOH
         tar -xzvf #{Chef::Config['file_cache_path']}/temp/temp.tgz -C #{Chef::Config['file_cache_path']}/temp
  2. Using ‘execute’ resource

    execute 'Verification Test' do
      cwd "#{Chef::Config['file_cache_path']}/temp"
      command <<-EOH
        tar -xzvf #{Chef::Config['file_cache_path']}/temp/temp.tgz -C #{Chef::Config['file_cache_path']}/temp
      live_stream true
      returns 0

Advantage of using ‘execute’ resource is, we can use ‘livestream’ property to print the output of the resource commands when chef client runs.

You may also like...

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.