Why Rsync Requires –rsync-path Even When Remote Rsync Is in $PATH: A Deep Dive


2 views

When running rsync over SSH, you might encounter this frustrating error:

$ rsync -avze 'ssh -p 22' --delete public/ user@host:~/public_html
bash: /usr/local/bin/rsync: No such file or directory
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: remote command not found (code 127) at io.c(601) [sender=3.0.7]

This happens despite rsync being properly installed in the remote system's /usr/bin directory and the $PATH environment variable being correctly set.

When rsync runs over SSH, it actually executes two separate processes:

  1. The local rsync client
  2. A remote rsync server process

The key insight is that the remote rsync process isn't launched through a shell login. Instead, SSH executes it directly with the specified command path.

Here's what's happening under the hood:

# What rsync tries to do:
ssh user@host /usr/local/bin/rsync --server --sender ...

# What you might expect:
ssh user@host rsync --server --sender ...

The remote rsync client hardcodes the path it expects to find the rsync binary in, rather than respecting the remote system's $PATH.

Here are three ways to solve this:

1. Using --rsync-path (Recommended)

rsync -avz --rsync-path=/usr/bin/rsync source/ user@host:dest/

2. Creating a Symlink

# On the remote server:
sudo ln -s /usr/bin/rsync /usr/local/bin/rsync

3. Using SSH Config

# In ~/.ssh/config
Host yourhost
    RemoteCommand PATH=/usr/bin:$PATH bash -l
    RequestTTY force

Many deployment tools (like Octopress's rake deploy) use rsync internally. If you're seeing this error in automated deployments, you'll need to:

# Modify your deployment command:
rsync -avze 'ssh -p 22' --rsync-path=/usr/bin/rsync --delete public/ user@host:~/public_html

To diagnose similar issues:

# Check where rsync is installed remotely
ssh user@host 'which rsync'

# Verify the remote PATH
ssh user@host 'echo $PATH'

# Test rsync execution directly
ssh user@host '/usr/bin/rsync --version'

Remember that environment variables (including PATH) might differ between interactive shells and command execution via SSH.


Many developers encounter this confusing scenario where rsync fails to locate the remote binary even when it's clearly in the remote system's PATH. Here's what's happening behind the scenes:

$ rsync -avze 'ssh -p 22' --delete public/ user@remote:~/public_html
bash: /usr/local/bin/rsync: No such file or directory
rsync: connection unexpectedly closed
rsync error: remote command not found (code 127)

When rsync initiates a remote connection, it doesn't actually use the remote shell's PATH environment variable. Instead:

  • rsync hardcodes a default search path (/usr/local/bin/rsync)
  • This behavior exists for security and predictability reasons
  • The remote shell's environment (including PATH) isn't loaded during initial handshake

The most reliable solution is to explicitly specify the remote rsync path:

$ rsync -avze 'ssh -p 22' --rsync-path=/usr/bin/rsync --delete source/ user@remote:dest/

Alternative approaches include:

# Using ssh config to set PATH
Host remote-server
    RemoteCommand PATH=/usr/bin:$PATH exec /bin/bash

When scripting rsync operations, always include --rsync-path for reliability:

#!/bin/bash
RSYNC_PATH=$(ssh user@remote "which rsync")
rsync -avz --rsync-path="$RSYNC_PATH" source/ user@remote:dest/

Understanding this behavior is crucial for:

  • CI/CD pipelines using rsync deployments
  • Cross-platform synchronization
  • Maintenance scripts running in restricted environments

The key takeaway: rsync's remote operation doesn't inherit the shell environment the way you might expect, so explicit path specification is often necessary for reliable operation.