download(from, to, options={}, &block)

The download action is used to transfer files (or even entire directory trees, though that'll be slow) from (potentially multiple) remote hosts to the local host, in parallel. It may be configured to use either SFTP or SCP to copy the files, defaulting to SFTP.

Note that because this helper uses the SCP and SFTP protocols, it isn't possible to "sudo". You need to make sure that the user you are logging into the server(s) as has the necessary permissions to read the files.



This must be a string indicating the path on the remote server that should be downloaded from. It may include the string $CAPISTRANO:HOST$, which will be replaced with the actual host name when the file is downloaded.

download("/etc/hosts", ...)
download("/usr/local/nginx/conf/server-$CAPISTRANO:HOST$.conf", ...)


This is a string identifying a file or directory name on the local host that you want to download the data to. It may include the special string $CAPISTRANO:HOST$, which will be replaced with the actual host name of the server being downloaded from. In fact, if you are downloading from multiple hosts simultaneously, you almost have to use $CAPISTRANO:HOST$ is the destination name, otherwise the servers will all be writing to the same file and you'll get a mess (if it works at all). By including the host name in the destination file, you can download each server's version of the file to a separate file locally.

download(/"etc/hosts", "downloads/hosts-$CAPISTRANO:HOST$")


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

This is a symbol indicating which protocol should be used to transfer the file or directory. If given, it must be either :sftp (the default), or :scp.
Either a string (for a single target host) or an array of strings, indicating which hosts should be downloaded from. By default, the hosts are determined from current task's roles.
Either a string or symbol (for a single target role) or an array of strings or symbols, indicating which roles should be downloaded from. If :hosts is specified, :roles will be ignored. By default, the roles are taken from the current task.
Specifies a condition limiting which hosts will be selected to download from. 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 }.
Specifies a condition limiting which hosts will be selected to download from. This is the inverse of :only (hosts that do not match the condition will be selected).
If true, only the first matching server will be selected. The default is false (all matching servers will be selected).
Specifies the maximum number of hosts that should be selected at a time. If this value is less than the number of hosts that are selected to download from, then the hosts will be downloaded from in groups of max_hosts. The default is nil, which indicates that there is no maximum host limit. Warning: this setting will probably be removed in a future release.

Note that the options are also passed directly through to the Net::SFTP (for :sftp) and Net::SCP (for :scp) libraries. Options exposed by those libraries are documented in those libraries. (For SFTP, see the Net::SFTP::Operations::Download module. For SCP, see the Net::SCP#download method.)


If no block is passed to download, a minimal amount of progress reporting on the download will be provided by default. (You'll see when each file is received from the server, and for SFTP, when the entire transfer finishes.) However, if you pass a block, it will be called to report status on the progress of the download.

The format of the block is different, depending on whether you are using SFTP or SCP.

SFTP progress callbacks

For SFTP transfers, the block should take three parameters:

 download("source", "target", :via => :sftp) do |event, options, *others|
   # ...

The event parameter is a symbol and will be indicate which event is being reported. It will be one of:

Indicates that a file is being opened in preparation for reception from the remote server. In this case, others[0] will be an object representing the file to be downloaded (see below).
Indicates that part (possibly all) of the current file is being downloaded. others[0] will be the file object (see below), others[1] will be the byte offset from which data is being received, and others[2] will be the actual data that was received. (Files will be received in chunks, so unless the files are very small you this will be called multiple times per file.)
Indicates that a file has finished downloading. others[0] will be the file object (see below).
This event is used to indicate that a (local) directory is being created (as part of downloading a directory tree). others[0] is the local path name in this case.
Indicates that all files have been transfered for the current server.

The file object mentioned above is a simple structure with a few useful attributes. You can do object.local to get the local file name, object.remote to get the remote file name, and object.size to get the size of the file.

The options parameter is a hash of useful properties specific to the current server. It will contain at least the following keys:

The host name of the current server.
A Capistrano::ServerDefinition object for the current server.

The others parameter is an array of additional arguments, interpreted differently by the different progress events.

SCP progress callbacks

The SCP protocol doesn't give as much notification a the SFTP protocol does. In this case, the block takes four arguments:

download("source", "target", :via => :scp) do |channel, name, received, total|
  # ...

Here, channel is the SSH channel over which the transfer is occurring. It can be used like a hash with the following keys:

The host name of the current server.
A Capistrano::ServerDefinition object for the current server.

The name argument is the name of the file being transfered. sent is the total number of bytes that have been received so far for the file, and total is the full size of the file being transferred.


Usually, you're only downloading a file from a single host. In that case, you might consider using the get helper instead, which is slightly simpler and optimized for that use case. However, if (for some reason) get won't work for you, and you still only want to download from a single host, you can pass the :once option:

download "/etc/hosts", "downloads/hosts", :once => true

Note that the download helper will not create destination directories, so you'll need to make sure they already exist before calling it:

FileUtils.mkdir_p "downloads"
download "/etc/hosts", "downloads/hosts", :once => true

See Also