Table Of Contents


A resource is a key part of a recipe that defines the actions that can be taken against a piece of the system. These actions are identified during each chef-client run as the resource collection is compiled. Once identified, each resource (in turn) is mapped to a provider, which then configures each piece of the system.

The script resource is used to execute scripts using the specified interpreter (Bash, csh, Perl, Python, or Ruby) and includes all of the actions and attributes that are available to the execute resource.


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. 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 the not_if and only_if meta parameters to guard the use of this resource for idempotence.

This resource is the base resource for several other resources used for scripting on specific platforms. For more information about specific resources for specific platforms, see the following topics:


The syntax for using the script resource in a recipe is as follows:

script "name" do
  some_attribute "value" # see attributes section below
  action :action # see actions section below


  • script tells the chef-client to use one of the following providers during the chef-client run: Chef::Resource::Script, Chef::Resource::Script::Bash, Chef::Resource::Script::Csh, Chef::Resource::Script::Perl, Chef::Resource::Script::Python, or Chef::Resource::Script::Ruby. The provider that is used by the chef-client depends on the platform of the machine on which the run is taking place
  • name is the name of the resource block; when the command attribute is not specified as part of a recipe, name is also the name of the command to be executed
  • attribute is zero (or more) of the attributes that are available for this resource
  • :action is the step that the resource will ask the provider to take during the chef-client run


This resource has the following actions:

Action Description
:run Default. Use to run a script.
:nothing Indicates that the command should not be run. This action is used to specify that a command is run only when another resource notifies it.


This resource has the following attributes:

Attribute Description
code A quoted (” ”) string of code to be executed.
command The name of the command to be executed. Default value: the name of the resource block (see Syntax section above).
creates Indicates that a command to create a file will not be run when that file already exists.
cwd The current working directory.
environment A Hash of environment variables in the form of {"ENV_VARIABLE" => "VALUE"}. (These variables must exist for a command to be run successfully.)
flags One (or more) command line flags that are passed to the interpreter when a command is invoked.
group The group name or group ID that must be changed before running a command.
interpreter The script interpreter to be used during code execution.
path 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.
provider Optional. Use to specify a provider by using its long name. For example: provider Chef::Provider::Long::Name. See the Providers section below for the list of providers available to this resource.
returns 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.
timeout The amount of time (in seconds) a command will wait before timing out. Default value: 3600.
user The user name or user ID that should be changed before running a command.
umask The file mode creation mask, or umask.


The following providers are available. Use the short name to use the provider in a recipe:

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.
Chef::Provider::Script::Csh csh The provider that is used with the csh command interpreter.
Chef::Provider::Script::Perl perl The provider that is used with the Perl command interpreter.
Chef::Provider::Script::Python python The provider that is used with the Python command interpreter.
Chef::Provider::Script::Ruby ruby The provider that is used with the Ruby 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

Run a script

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

or something like:

bash "openvpn-server-key" do
  environment("KEY_CN" => "server")
  code <<-EOF
    openssl req -batch -days #{node["openvpn"]["key"]["expire"]} \
      -nodes -new -newkey rsa:#{key_size} -keyout #{key_dir}/server.key \
      -out #{key_dir}/server.csr -extensions server \
      -config #{key_dir}/openssl.cnf
  not_if { ::File.exists?("#{key_dir}/server.crt") }

where code contains the OpenSSL command to be run. The not_if method tells the chef-client not to run the command if the file already exists.

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#{node['nginx']['foo123']['version']}.tar.gz"
src_filepath = "#{Chef::Config['file_cache_path']}/#{src_filename}"
extract_path = "#{Chef::Config['file_cache_path']}/nginx_foo123_module/#{node['nginx']['foo123']['checksum']}"

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

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 "0644"
  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) }