#!/bin/sh ## In order for this script to work, the following must be installed (except ## for pv, these should all be in your base systems): ## ## On the local host : ssh expr pv ## On the source host : ssh du cut tail ## On the destination host : ssh du cut touch cat ## ## Exit status is 0 on success, 2 if the destination file is the same size ## as the source file. If one of the commands fails, it'll probably exit ## with a 1. The external commands might exit 2 as well; if you have verbose ## on, then you'll see a message on stderr from this script if it's exiting 2 ## because the files were the same size (so if you have an exitstatus of 2 and ## no message, you know it came from an external command). ## Hostnames of the two servers, as you would pass them to the SSH client source_host="srchost" destination_host="desthost" ## These filenames are going straight to the SSH client, so relative paths ## are relative to your home directory on each remote system. ## ## There's no reason the file in question has to be a .gz file, I'm just using ## that extension as an example; any file will work the same way. ## ## You can leave the destination filename empty and the source filename will ## be used (including any path) source_filename="testfile.gz" #destination_filename="" ## Set this to >0 to have the script print some diagnostics to stderr verbose=1 ############################################################################### ############################################################################### ## Retrieve the source file's size source_file_size=$(ssh "${source_host}" "du --bytes ${source_filename} | cut --fields 1") ## Use source filename for destination of we don't already have one [ -z "${destination_filename}" ] && destination_filename="${source_filename}" ## Retrieve the destination file's size destination_file_size=$(ssh "${destination_host}" "du --bytes ${destination_filename} 2>/dev/null | cut --fields 1") [ -z "${destination_file_size}" ] && destination_file_size=0 if [ ${destination_file_size} -eq ${source_file_size} ]; then ## Files are the same size, we must be done; exit with a unique status [ ${verbose} -ge 1 ] && echo "File sizes are the same; looks like we're done." >&2 exit 2 fi if [ ${destination_file_size} -gt 0 ]; then byte_offset=$(expr ${destination_file_size} + 1) transfer_size=$(expr ${source_file_size} - ${destination_file_size}) else byte_offset=0 transfer_size=${source_file_size} fi if [ ${verbose} -ge 1 ]; then ## Print diagnostics to stderr echo "Source : ${source_host}:${source_filename}" >&2 echo "Destination : ${destination_host}:${destination_filename}" >&2 echo "Source file size : ${source_file_size}" >&2 echo "Destination file size : ${destination_file_size}" >&2 echo "Byte offset : ${byte_offset}" >&2 echo "Transfer size : ${transfer_size}" >&2 echo "" >&2 echo "###############################################################################" >&2 echo "" >&2 fi ## Release the hounds! ssh "${source_host}" "tail -c +${byte_offset} ${source_filename}" | pv -s ${transfer_size} | ssh "${destination_host}" "touch ${destination_filename}; cat - >> ${destination_filename}" ## EOF ########