Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

2.x DSL Action Invocation Run

dubek edited this page · 11 revisions

Definition

run(command, options={}, &block)

Module

Capistrano::Configuration::Actions::Invocation

The run action is used to execute commands on one or more servers. It can be used to execute arbitrary shell commands, including any POSIX shell script syntax. It may also be given a block in order to capture output from and interact with the remote command.

The run command will execute the command on all matching servers ''simultaneously''. People frequently want to know which server a command is being executed on at a particular moment--the answer is, honestly, "all of them." (If you want to try and do different things on different servers in parallel, check out the parallel helper.)

Arguments

:command

This must be a string containing the shell command (or commands) to execute. It may be any valid POSIX shell command, including multiple commands combined using semicolons, pipes, or ampersands. No escaping of the input is performed.

If the command is determined to include a [[sudo|http://github.com/capistrano/capistrano/wiki/2.x-DSL-Action-Invocation-Sudo]] invocation, run will also (by default) look for sudo prompts and, if found, will prompt the user for a password and pass what is entered back to the command.

Examples:

run "ln -s /usr/local/bin/ruby /usr/bin/ruby"
run "ls -l \"~/Project Folders\""
run "if [ -d /u/apps/social ]; then cd /u/apps/social && git pull; else cd /u/apps && git clone git://github.com/me/social.git; fi"
run "#{[[sudo|http://github.com/capistrano/capistrano/wiki/2.x-DSL-Action-Invocation-Sudo]]} apachectl restart"

Note that if you embed the special string $CAPISTRANO:HOST$ anywhere inside of a command, it will be replaced with the host name of the server on which the command is being executed. In this way, you can tailor commands so that they work slightly differently for different hosts:

run "cp /u/apps/social/config/solr-$CAPISTRANO:HOST$.conf /u/apps/social/config/solr.conf"
run "/u/apps/social/script/init-$CAPISTRANO:HOST$.sh"

Similarly, if you embed the string `$CAPISTRANO:HOSTROLES$, it will be replaced with a comma separated list of the roles assigned to the host. This can be useful when invoking a configuration management tool like chef solo. For example, you can invoke chef-solo with soloist, configuring the run list based on the roles assigned to each host:

run "cd #{deploy_to} && ROLES=$CAPISTRANO:HOSTROLES$ soloist"

For changing the command per-host more significantly, see [[parallel|2.x-DSL-Action-Invocation-Parallel]].

:options

The options hash can be used to modify the default behavior of run. Recognized options are:

:hosts

Either a string (for a single target host) or an array of strings, indicating which hosts the command should run on. By default, the hosts are determined from current task's roles. This can also a Proc object, in which case it will be invoked and the return value used as the host list. (This can be useful for deferred calculation of the hosts to use, especially when passed as an option to [[task|2.x-DSL-Configuration-Tasks-Task]].)

:roles

Either a string or symbol (for a single target role) or an array of strings or symbols, indicating which roles the command should run on. If :hosts is specified, :roles will be ignored. By default, the roles are taken from the current task. This can also be a Proc object, in which case it will be invoked and the return value used as the roles list. (This can be useful for deferred calculation of the roles to use, especially when passed as an option to [[task|2.x-DSL-Configuration-Tasks-Task]].)

:on_no_matching_servers

If set to :continue then skips this execution if there are no matching hosts that should run the command. The default behavior is to fail if there are no matching hosts.

:only

Specifies a condition limiting which hosts will be selected to run the command. This should refer to values set in the [[role]]. For example, if a role is defined with :primary => true, then you could select only hosts with that setting by specifying :only => { :primary => true }.

:except

Specifies a condition limiting which hosts will be selected to run the command. This is the inverse of :only (hosts that do ''not'' match the condition will be selected).

:once

If true, only the first matching server will be selected. The default is false (all matching servers will be selected).

:shell

Says which shell should be used to invoke commands. This defaults to "sh", but you could use this to select (e.g.) "/bin/bash" if a bare "sh" doesn't work on your system for some reason. Setting this to false causes Capistrano to invoke the command directly, without going through a separate shell.

:data

If not nil (the default), this should be a string that will be passed to the command's stdin stream. This can be used to "prime the pump", if some command needs some initial interaction before doing something useful.

:pty

If true, a pseudo-tty will be allocated for each command. The default is false. Note that there are benefits and drawbacks both ways. Empirically, it appears that if a pty is allocated, most SSH server daemons will ''not'' read user shell start-up scripts (e.g. bashrc, etc.). However, if a pty is ''not'' allocated, some commands (like sudo, or git, or svn) will run in non-interactive mode and will not prompt for (e.g.) passwords. You have to choose your poison, apparently.

:env

A hash of environment variable mappings that should be made available to the command. The keys should be environment variable names, and the values should be their corresponding values. The default is empty, but may be modified by changing the [[default_environment]] Capistrano variable.

Note that any of these keys can be set in the [[default_run_options]] hash. If they are, the values you specify will be used as the defaults for subsequent invocations of run, [[invoke_command]], [[sudo|http://github.com/capistrano/capistrano/wiki/2.x-DSL-Action-Invocation-Sudo]], and [[parallel]].

&block

If no block is passed to run, run will default to echoing all output from the command. If you specify a block, however, you can capture and process the output from the command as the command emits it, and you can also send data back on the command's stdin stream.

The block takes three parameters:

run "command" do |channel, stream, data|
 # ...
end

The channel parameter is the SSH channel object that is hosting the command. This is used to send data back to the command, as well as to determine which server sent the data to you (since commands are run in parallel on all matching servers).

run "command" do |channel, stream, data|
 puts "host-name: " + channel[:host]        # server host name, as a string
 puts "server object: " + channel[:server]  # Capistrano::ServerDefinition object for the server
 channel.send_data("password\n")            # send data back via the remote command's stdin stream
end

The stream parameter is a symbol, either :out (for stdout) or :err (for stderr), indicating which output stream the data arrived on. You can use this to differentiate between streams, if you need to. For instance, if you know that any data from stderr means an error happened, you can act accordingly when stream is :err.

Lastly, the data parameter is a string containing the data emitted by the command. It is important to note that all of a command's output may not be sent in a single chunk. In fact, the data may not even be entirely line-wise. Thus, a single command may result in multiple invocations of the block, with each data chunk being the next block of data from the command.

This is further complicated by the fact that each ''server'' will use the same callback, so if you are invoking a command on three servers, each of those three command invocations will use the same block. If you need to interact with the remote commands, you can use channel[:host] and channel[:server] to determine which server sent the data.

Run commands locally

The run helper may not be appropriate for running commands which do not need to be executed remotely. Such commands, for example repository checks or shared location file copying, can be run from the server on which the deploy script itself is run. In such instances, use ''run_locally''. An example would be a task to output a list of tagged releases.

run_locally "svn ls -v #{repository_root}/releases | awk '{print $1\",\"$2\",\"$3\",\"$4\",\"$5\",\"$6}'"

and

run "svn ls -v #{repository_root}/releases | awk '{print $1\",\"$2\",\"$3\",\"$4\",\"$5\",\"$6}'"

Both commands appear to be the same, but the second would be executed on each server (assuming more than one server exists for a given role).

A good way to illustrate the differences between run and run_locally is with the following basic task:

task :illustrate_run do
  run_locally "hostname"
  run "hostname" do |c,s,d|
    puts d
  end
end
Something went wrong with that request. Please try again.