Rsync (rsync v0.2.0)

View Source

Wrapper for the rsync command, reporting percent completion

The main entry point is sync/3, which starts a linked GenServer to monitor the transfer. The simplest usage would be to simply wait for the subprocess to complete successfully. Progress can be monitored by calling get_progress/1 or the caller can subscribe to receive progress messages as they are emitted by rsync, using the :listener option.

Errors and unrecognized status lines are logged, and overall success or error is reported using the GenServer exit reason.

Be extremely cautious when building source and target arguments, there is no built-in protection against filesystem traversal. Use Path.safe_relative/2 and the included remote_path/3 according to your expected needs.

Examples

Push a file to the default user's home directory on a remote server:

Rsync.sync("local_file.txt", "host:")

Retrieve several remote files:

Rsync.sync(
  Rsync.remote_path(filenames, user, host),
  "local_path/"
)

Set up real-time monitoring of a transfer:

Rsync.sync("local_path", "host:remote_path", listener: self())

receive do
  {:progress, fraction_complete} ->
    IO.puts("Transfer #{fraction_complete * 100}% complete")

  {:exit_status, 0} ->
    IO.puts("Transfer successfully completed.")
end

Kill a transfer:

{:ok, pid} = Rsync.sync("local", "remote")

Rsync.stop(pid)

Handle unsuccessful exit using a Supervisor or by trapping the linked signal:

Process.flag(:trap_exit, true)

Rsync.sync("source", "target")

receive do
  {:EXIT, _pid, {:error, exit_status}} ->
    IO.puts("Failed with code: #{exit_status}")
end

Summary

Functions

Returns a specification to start this module under a supervisor.

Return overall tranfer progress as a floating point number between 0 and 1.

Start rsync file copy

Types

option()

@type option() ::
  {:env, [{charlist(), charlist()}]}
  | {:exe, binary()}
  | {:keyfile, binary()}
  | {:listener, pid()}
  | {:rsync_args, [binary()]}
  | {:ssh_args, [binary()]}
  | {:source, path_or_paths()}
  | {:target, binary()}

options()

@type options() :: [option()]

path_or_paths()

@type path_or_paths() :: binary() | [binary()]

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

get_progress(pid)

@spec get_progress(pid()) :: float()

Return overall tranfer progress as a floating point number between 0 and 1.

remote_path(paths, host)

@spec remote_path(path :: path_or_paths(), host :: binary()) :: [binary()] | binary()

remote_path(path, user, host)

@spec remote_path(path :: path_or_paths(), user :: binary(), host :: binary()) ::
  [binary()] | binary()

start_link(args, opts \\ [])

@spec start_link(options(), GenServer.options()) :: GenServer.on_start()

stop(pid)

@spec stop(pid()) :: :ok

sync(source, target, opts \\ [])

@spec sync(path_or_paths(), binary(), options()) :: GenServer.on_start()

Start rsync file copy

Options

  • :env - Charlist tuples of environment variables to set. Example: env: [{~c"RSYNC_PARTIAL_DIR", ~c".rsync-partial"}]

  • :exe - Path to the rsync executable. Defaults to the first rsync in PATH.

  • :keyfile - Path to ssh private identity. Will be shell-expanded. Example: keyfile: "~/.ssh/id_rsa-bot"

  • :listener - Process which will listen for progress updates. This process may receive two message formats:

    • {:progress, float()} - Fractional completion, such as 0.1 for 10% overall progress.

    • {:exit_status, int()} - Sent when the sync is finished, with an exit status that should equal 0 on success.

  • :rsync_args - Commandline options to pass to rsync. Example: rsync_args: ~w(--delete --checksum)

  • :ssh_args - Commandline options to pass to ssh. Will be shell-expanded. Example: ssh_args: ~w(-i ~/.ssh/id_rsa-bot -o StrictHostKeyChecking=no)

  • :source - Source file or directory, or list of sources. Follows the same rules as rsync, where any source directory name ending in "/" will be copied to the top level without nesting under a directory on the target. Remote sources should each be prepended with user and hostname, which can be aided by remote_path/3.

  • :target - Target file or directory. Remote target can be constructed by remote_path/3, for example target: "user@host:/path"