Using rsync over ssh when the remote side is a chroot shell

Just a tip; the rsync download listed later in this article works on VMware ESXi too!

October 2020 Update:

This process continues to work for vSphere since Vmware continues to not give us an rsync binary in ESXi. Here’s my 2020 version followed by the original. The resulting binary seems to work fine on ESXi 6.5 without any special build flags, assuming you have an old system to compile on.

  1. Download the SRPM for rsync from CentOS 3: http://vault.centos.org/3.9/os/SRPMS/rsync-2.5.7-5.3E.src.rpm
  2. I installed the above to an old CentOS 4 VM I keep sitting around for this kind of crap; have not tested on newer CentOS versions.
  3. Extract, build:
cd /usr/src/redhat/SOURCES/
tar zxvf rsync-2.5.7.tar.gz
cd rsync-2.5.7
./configure
make
strip rsync-static
  1. Copy the rsync-static to your ESXi server.
  2. rsync your content in using the –rsync-path argument to tell it where the remote binary is:
rsync -avz --progress \
--rsync-path=/rsync-static \
-e ssh testmachine/testmachine.vmdk \
vsphere.host:/vmfs/volumes/aaaaaaa-bbbbbb-cccc-00000000/testmachine/

Original:

Ever need to copy files using rsync from a remote server and the remote server is using some kind of restricted shell that keeps you from executing the system rsync?  Fortunately, rsync itself has a command line argument to help get around that provided you can upload your own copy to the remote server that will execute; i.e. statically compile for the remote OS if possible.

The command line argument that makes the magic happen is –rsync-path=.  It lets you tell the local copy of rsync where the remote copy of rsync is.  For example, if you’re copying from a remote server where rsync is in a directory called /private and is named rsync-static, then run:

rsync -avz --delete --progress \
 --rsync-path=/private/rsync-static \
 -e ssh user@remote-server:/html /var/www/

Getting a statically compiled rsync has proven to be a bit more of a challenge though.  I found numerous online resources that suggested compiler flags:

make CFLAGS="-static" EXEEXT="-static"

or even a complete gcc command:

gcc --static -std=gnu99 -g -O2 -DHAVE_CONFIG_H -Wall -W -o rsync flist.o rsync.o generator.o receiver.o cleanup.o sender.o exclude.o util.o main.o checksum.o match.o syscall.o log.o backup.o options.o io.o compat.o hlink.o token.o uidlist.o socket.o hashtable.o fileio.o batch.o clientname.o chmod.o acls.o xattrs.o progress.o pipe.o params.o loadparm.o clientserver.o access.o connection.o authenticate.o lib/wildmatch.o lib/compat.o lib/snprintf.o lib/mdfour.o lib/md5.o lib/permstring.o lib/pool_alloc.o lib/sysacls.o lib/sysxattrs.o zlib/deflate.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o zlib/trees.o zlib/zutil.o zlib/adler32.o zlib/compress.o zlib/crc32.o -lacl -lpopt

None of these worked for me.  The closest I could get, after installing libacl-devel and popt-devel via yum, was still an error:

make CFLAGS="-static" EXEEXT="-static" gcc -std=gnu99 -static -o rsync-static flist.o rsync.o generator.o receiver.o cleanup.o sender.o exclude.o util.o main.o checksum.o match.o syscall.o log.o backup.o options.o io.o compat.o hlink.o token.o uidlist.o socket.o hashtable.o fileio.o batch.o clientname.o chmod.o acls.o xattrs.o progress.o pipe.o params.o loadparm.o clientserver.o access.o connection.o authenticate.o lib/wildmatch.o lib/compat.o lib/snprintf.o lib/mdfour.o lib/md5.o lib/permstring.o lib/pool_alloc.o lib/sysacls.o lib/sysxattrs.o zlib/deflate.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o zlib/trees.o zlib/zutil.o zlib/adler32.o zlib/compress.o zlib/crc32.o -lacl -lpopt /usr/bin/ld: cannot find -lpopt collect2: ld returned 1 exit status make: *** [rsync-static] Error 1

I have no idea why that is occurring since the popt-devel package is installed and /usr/include/popt.h is present.  If anyone has a solution please send it my way.  Until then, I found someone else’s static rsync that I had to trust enough to run on someone else’s remote server lol, it worked though, so perhaps it’s good for you too:  http://www.stearns.org/rsync-static/filelist.html

http://www.stearns.org/rsync-static/rsync-static-2.5.7-1.i386.rpm

Extract the linux binary out of it using:

rpm2cpio rsync-static-2.5.7-1.i386.rpm |cpio -ivd ./usr/bin/rsync-static

It worked fine for me on CentOS 6 x86_64.