Use the bash resource to execute scripts using the Bash interpreter. This resource may also use any of the actions and properties that are available to the execute resource. Commands that are executed with this resource are (by their nature) not idempotent, as they are typically unique to the environment in which they are run. Use not_if and only_if to guard this resource for idempotence.


The bash script resource (which is based on the script resource) is different from the ruby_block resource because Ruby code that is run with this resource is created as a temporary file and executed like other script resources, rather than run inline.


A bash resource block executes scripts using Bash:

bash 'extract_module' do
  cwd ::File.dirname(src_filepath)
  code <<-EOH
    mkdir -p #{extract_path}
    tar xzf #{src_filename} -C #{extract_path}
    mv #{extract_path}/*/* #{extract_path}/
  not_if { ::File.exists?(extract_path) }


  • cwd specifies the directory from which the command is run
  • code specifies the command to run

The full syntax for all of the properties that are available to the bash resource is:

bash 'name' do
  code                       String
  creates                    String
  cwd                        String
  environment                Hash
  flags                      String
  group                      String, Integer
  notifies                   # see description
  path                       Array
  provider                   Chef::Provider::Script::Bash
  returns                    Integer, Array
  subscribes                 # see description
  timeout                    Integer, Float
  user                       String, Integer
  umask                      String, Integer
  action                     Symbol # defaults to :run if not specified


  • bash is the resource
  • name is the name of the resource block
  • cwd is the location from which the command is run
  • :action identifies the steps the chef-client will take to bring the node into the desired state
  • code, creates, cwd, environment, flags, group, path, provider, returns, timeout, user, and umask are properties of this resource, with the Ruby type shown. See “Properties” section below for more information about all of the properties that may be used with this resource.


This resource has the following actions:

Action Description
:nothing Prevent a command from running. This action is used to specify that a command is run only when another resource notifies it.
:run Default. Run a script.


This resource has the following properties:

Property Description

Ruby Type: String

A quoted (” ”) string of code to be executed.


Ruby Type: String

Prevent a command from creating a file when that file already exists.


Ruby Type: String

The current working directory.


Ruby Type: Hash

A Hash of environment variables in the form of {"ENV_VARIABLE" => "VALUE"}. (These variables must exist for a command to be run successfully.)


Ruby Type: String

One or more command line flags that are passed to the interpreter when a command is invoked.


Ruby Types: String, Integer

The group name or group ID that must be changed before running a command.


Ruby Types: TrueClass, FalseClass

Continue running a recipe if a resource fails for any reason. Default value: false.


Ruby Type: Symbol, ‘Chef::Resource[String]’, Symbol

Which resource takes action when this resource’s state changes. A resource may notify more than one resource; use a notifies statement for each resource to be notified.

Specify the :action, 'resource[name]', and timer (:delayed or :immediately). Use multiple notifies statements to notify more than one resource.

resource 'name' do
  notifies :action, 'resource[name]', :timer

Use the following timers to specify when a notification is triggered:

Timer Description
:delayed Use to specify that a notification should be queued up, and then executed at the very end of a chef-client run.
:immediately Use to specify that a notification should be run immediately, per resource notified.

Ruby Type: Array

An array of paths to use when searching for a command. These paths are not added to the command’s environment $PATH. The default value uses the system path.


The path property is not implemented by any provider in any version of the chef-client. Starting with chef-client 12, using the path property will return a warning. Starting with chef-client 13, the path property is deprecated and using it will return an exception. Cookbooks that currently use the path property should be updated to use the environment property instead.

For example:

bash 'mycommand' do
  environment 'PATH' => "/my/path/to/bin:#{ENV['PATH']}"

Ruby Type: Chef Class

Optional. Explicitly specify a provider. See “Providers” section below for more information.


Ruby Type: Integer

The number of times to catch exceptions and retry the resource. Default value: 0.


Ruby Type: Integer

The retry delay (in seconds). Default value: 2.


Ruby Types: Integer, Array

The return value for a command. This may be an array of accepted values. An exception is raised when the return value(s) do not match. Default value: 0.


Ruby Type: Symbol, ‘Chef::Resource[String]’, Symbol

Specify that this resource is to listen to another resource, and then take action when that resource’s state changes.

Specify the :action, 'resource[name]', and timer (:delayed or :immediately). Use multiple subscribes statements to listen to more than one resource.

resource 'name' do
  subscribes :action, 'resource[name]', :timer

The subscribes property uses the same timers as the notifies property.


Ruby Types: Integer, Float

The amount of time (in seconds) a command is to wait before timing out. Default value: 3600.


Ruby Types: String, Integer

The user name or user ID that should be changed before running a command.


Ruby Types: String, Integer

The file mode creation mask, or umask.


A guard property can be used to evaluate the state of a node during the execution phase of the chef-client run. Based on the results of this evaluation, a guard property is then used to tell the chef-client if it should continue executing a resource. A guard property accepts either a string value or a Ruby block value:

  • A string is executed as a shell command. If the command returns 0, the guard is applied. If the command returns any other value, then the guard property is not applied. String guards in a powershell_script run Windows PowerShell commands and may return true in addition to 0.
  • A block is executed as Ruby code that must return either true or false. If the block returns true, the guard property is applied. If the block returns false, the guard property is not applied.

A guard property is useful for ensuring that a resource is idempotent by allowing that resource to test for the desired state as it is being executed, and then if the desired state is present, for the chef-client to do nothing.


The following properties can be used to define a guard that is evaluated during the execution phase of the chef-client run:

Guard Description
not_if Prevent a resource from executing when the condition returns true.
only_if Allow a resource to execute only if the condition returns true.


The following arguments can be used with the not_if or only_if guard properties:

Argument Description

Specify the user that a command will run as. For example:

not_if 'grep adam /etc/passwd', :user => 'adam'

Specify the group that a command will run as. For example:

not_if 'grep adam /etc/passwd', :group => 'adam'

Specify a Hash of environment variables to be set. For example:

not_if 'grep adam /etc/passwd', :environment => {
  'HOME' => '/home/adam'

Set the current working directory before running a command. For example:

not_if 'grep adam passwd', :cwd => '/etc'

Set a timeout for a command. For example:

not_if 'sleep 10000', :timeout => 10


Where a resource represents a piece of the system (and its desired state), a provider defines the steps that are needed to bring that piece of the system from its current state into the desired state.

The chef-client will determine the correct provider based on configuration data collected by Ohai at the start of the chef-client run. This configuration data is then mapped to a platform and an associated list of providers.

Generally, it’s best to let the chef-client choose the provider and this is (by far) the most common approach. However, in some cases specifying a provider may be desirable. There are two approaches:

  • Use a more specific short name—yum_package "foo" do instead of package "foo" do, script "foo" do instead of bash "foo" do, and so on—when available
  • Use the provider property within the resource block to specify the long name of the provider as an property of a resource. For example: provider Chef::Provider::Long::Name

This resource has the following providers:

Long name Short name Notes
Chef::Provider::Script script When this short name is used, the chef-client will determine the correct provider during the chef-client run.
Chef::Provider::Script::Bash bash The provider that is used with the Bash command interpreter.


The following examples demonstrate various approaches for using resources in recipes. If you want to see examples of how Chef uses resources in recipes, take a closer look at the cookbooks that Chef authors and maintains:

Use a named provider to run a script

bash 'install_something' do
  user 'root'
  cwd '/tmp'
  code <<-EOH
  tar -zxf tarball.tar.gz
  cd tarball
  make install

Install a file from a remote location using bash

The following is an example of how to install the foo123 module for Nginx. This module adds shell-style functionality to an Nginx configuration file and does the following:

  • Declares three variables
  • Gets the Nginx file from a remote location
  • Installs the file using Bash to the path specified by the src_filepath variable
# the following code sample is similar to the ``upload_progress_module``
# recipe in the ``nginx`` cookbook:

src_filename = "foo123-nginx-module-v#{
src_filepath = "#{Chef::Config['file_cache_path']}/#{src_filename}"
extract_path = "#{

remote_file 'src_filepath' do
  source node['nginx']['foo123']['url']
  checksum node['nginx']['foo123']['checksum']
  owner 'root'
  group 'root'
  mode '0755'

bash 'extract_module' do
  cwd ::File.dirname(src_filepath)
  code <<-EOH
    mkdir -p #{extract_path}
    tar xzf #{src_filename} -C #{extract_path}
    mv #{extract_path}/*/* #{extract_path}/
  not_if { ::File.exists?(extract_path) }

Install an application from git using bash

The following example shows how Bash can be used to install a plug-in for rbenv named ruby-build, which is located in git version source control. First, the application is synchronized, and then Bash changes its working directory to the location in which ruby-build is located, and then runs a command.

 git "#{Chef::Config[:file_cache_path]}/ruby-build" do
   repository 'git://'
   reference 'master'
   action :sync

 bash 'install_ruby_build' do
   cwd '#{Chef::Config[:file_cache_path]}/ruby-build'
   user 'rbenv'
   group 'rbenv'
   code <<-EOH
   environment 'PREFIX' => '/usr/local'

To read more about ruby-build, see here:

Store certain settings

The following recipe shows how an attributes file can be used to store certain settings. An attributes file is located in the attributes/ directory in the same cookbook as the recipe which calls the attributes file. In this example, the attributes file specifies certain settings for Python that are then used across all nodes against which this recipe will run.

Python packages have versions, installation directories, URLs, and checksum files. An attributes file that exists to support this type of recipe would include settings like the following:

default['python']['version'] = '2.7.1'

if python['install_method'] == 'package'
  default['python']['prefix_dir'] = '/usr'
  default['python']['prefix_dir'] = '/usr/local'

default['python']['url'] = ''
default['python']['checksum'] = '80e387...85fd61'

and then the methods in the recipe may refer to these values. A recipe that is used to install Python will need to do the following:

  • Identify each package to be installed (implied in this example, not shown)
  • Define variables for the package version and the install_path
  • Get the package from a remote location, but only if the package does not already exist on the target system
  • Use the bash resource to install the package on the node, but only when the package is not already installed
#  the following code sample comes from the ``oc-nginx`` cookbook on |github|:

version = node['python']['version']
install_path = "#{node['python']['prefix_dir']}/lib/python#{version.split(/(^\d+\.\d+)/)[1]}"

remote_file "#{Chef::Config[:file_cache_path]}/Python-#{version}.tar.bz2" do
  source "#{node['python']['url']}/#{version}/Python-#{version}.tar.bz2"
  checksum node['python']['checksum']
  mode '0755'
  not_if { ::File.exists?(install_path) }

bash 'build-and-install-python' do
  cwd Chef::Config[:file_cache_path]
  code <<-EOF
    tar -jxvf Python-#{version}.tar.bz2
    (cd Python-#{version} && ./configure #{configure_options})
    (cd Python-#{version} && make && make install)
  not_if { ::File.exists?(install_path) }