Last active
April 25, 2024 07:34
-
-
Save BMTLab/8ebb2cbfd5a3ed5c0584bb30831ff5d8 to your computer and use it in GitHub Desktop.
Wrapper for rsync, optimized for faster network transfers. It simplifies rsync's configuration to enhance usability & performance
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# shellcheck disable=SC2034 | |
# Author: Nikita Neverov (BMTLab) | |
# Version: 2.1.7 | |
readonly ERR_FRSYNC_INVALID_OPTIONS=101 | |
####################################### | |
# frsync: Optimizes the file synchronization process from local to remote using rsync over SSH or vice versa. | |
# The function is designed for advanced users needing fine-grained control over file transfer settings, | |
# aiming to achieve the highest possible performance. It includes options for enabling SSH compression, | |
# utilizing custom SSH private keys, managing SSH connection multiplexing, and ensuring file consistency | |
# with the --delete option. It also provides mechanisms to bypass SSH security checks in trusted networks | |
# for faster setup. This function embodies a balance between speed, security, and flexibility, offering | |
# users a powerful tool for their file synchronization needs. | |
# | |
# Globals: | |
# ERR_FRSYNC_INVALID_OPTIONS - Error code for invalid options. | |
# | |
# Arguments: | |
# -h - Displays help message and exits. | |
# -c - Enables compression during the transfer to improve speed over slow connections. | |
# -i <private_key> - Specifies a path to the SSH private key for secure authentication. | |
# -m - Disables SSH connection multiplexing (ControlMaster and ControlPath), useful in environments where SSH multiplexing might not be supported. | |
# -d - Enables the --delete option in rsync to ensure the receiving side mirrors the source by deleting extraneous files. | |
# -u - Enables unsafe SSH options for faster communication in trusted networks, such as disabling strict host key checking. | |
# <local_path1> [<local_path2> ...] <remote_user@remote_ip:remote_path> - Specifies local and remote paths for rsync. | |
# | |
# Outputs: | |
# Writes messages to stdout and stderr, providing detailed feedback on the transfer process. | |
# Exits with various status codes based on success or type of error encountered during execution. | |
# | |
# Returns: | |
# 0 - Successful execution. | |
# ERR_FRSYNC_INVALID_OPTIONS(101) - Returned in case of invalid command-line options. | |
# Other non-zero status - Returned in case of errors during rsync execution. | |
####################################### | |
function frsync() { | |
local help_message | |
# Multi-line usage message | |
read -r -d '' help_message << 'EOF' | |
Usage: frsync [-h] [-c] [-i private_key] [-m] [-d] [-u] <local_path1> [<local_path2> ...] <remote_user@remote_ip:remote_path> | |
Options: | |
-h: Display this help message and exit. | |
-c: Enable compression during transfer. | |
-i: Specify a path to the SSH private key for authentication. | |
-m: Disable SSH connection multiplexing (ControlMaster and ControlPath). | |
-d: Enable the --delete option in rsync to delete extraneous files from the receiving side. | |
-u: Enable unsafe SSH options for faster communication, but only in trusted networks. | |
This function preconfigures rsync for faster network transfers by optimizing various settings. | |
EOF | |
# Prints help message | |
function __frsync_usage() { | |
printf '%b\n' "$help_message" | |
unset -f __frsync_usage | |
} | |
# Prints error message | |
function __frsync_error() { | |
local -r message="$1" | |
local -ir code="${2:-$ERR_FRSYNC_INVALID_OPTIONS}" | |
printf 'Error: %s.\n\n' "$message" >&2 | |
__frsync_usage | |
unset -f __frsync_error | |
return $code | |
} | |
local private_key_option='' | |
local is_private_key_option_set=false | |
local enable_compression=false | |
local disable_multiplexing=false | |
local enable_rsync_delete=false | |
local enable_unsafe_options=false | |
## Process command-line options | |
# This ensures that getopts always starts processing arguments from the first argument each time | |
# the frsync function is called, and should fix the problem of missing options on repeated calls. | |
OPTIND=1 | |
local opt | |
while getopts ':hci:mdu' opt; do | |
case "$opt" in | |
h) | |
__frsync_usage | |
return 0 | |
;; | |
c) | |
enable_compression=true | |
;; | |
i) | |
if [[ -z $OPTARG ]]; then | |
__frsync_error 'Option -i requires an argument' || return $? | |
fi | |
private_key_option="$OPTARG" | |
is_private_key_option_set=true | |
;; | |
m) | |
disable_multiplexing=true | |
;; | |
d) | |
enable_rsync_delete=true | |
;; | |
u) | |
enable_unsafe_options=true | |
;; | |
\?) | |
__frsync_error "Invalid option: -${OPTARG}" || return $? | |
;; | |
:) | |
__frsync_error "Option -${OPTARG} requires an argument" || return $? | |
;; | |
esac | |
done | |
# We remove the processed options, leaving only the path arguments | |
shift $((OPTIND - 1)) | |
# Verify that at least two arguments remain (local and remote paths) | |
if [ "$#" -lt 2 ]; then | |
__frsync_error 'Local and remote host must be specified' || return $? | |
fi | |
# Calculates local and remote hosts | |
local -r remote_path="${!#}" # Get the last argument as the remote path | |
local -ar local_path_arr=("${@:1:$#-1}") # Define as an array of all arguments except the last one | |
# Tuning RSYNC options | |
local -a rsync_options_arr=('-aHAXxv' '--numeric-ids' '--progress' '--partial' '--inplace') | |
[[ $enable_rsync_delete == true ]] && rsync_options_arr+=('--delete') | |
[[ $enable_compression == true ]] && rsync_options_arr+=('-z') | |
# Tuning SSH options | |
local -a ssh_options_arr=('-T' '-c' 'chacha20-poly1305@openssh.com') # Fastest encryption algorthym | |
[[ $is_private_key_option_set == true ]] && ssh_options_arr+=('-i' "$private_key_option") | |
[[ $disable_multiplexing == false ]] && ssh_options_arr+=('-o' 'ControlMaster=auto' '-o' 'ControlPath=/tmp/frsync-%r@%h:%p') | |
[[ $enable_unsafe_options == true ]] && ssh_options_arr+=('-o' 'StrictHostKeyChecking=no' '-o' 'UserKnownHostsFile=/dev/null') | |
ssh_options_arr+=('-o' 'ForwardX11=no') | |
# ssh_options_arr+=('-v') # DEBUG | |
local -r ssh_command="ssh $(printf '%q ' "${ssh_options_arr[@]}")" | |
# Execute rsync with the predefined options | |
rsync "${rsync_options_arr[@]}" -e "$ssh_command" "${local_path_arr[@]}" "$remote_path" | |
unset -f __frsync_usage __frsync_error | |
} | |
readonly -f frsync |
Author
BMTLab
commented
Apr 25, 2024
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment