Compare commits

...

2 Commits

Author SHA1 Message Date
Michael Krayer ccd4d37027 number of streams is specified as optional argument now 2024-04-02 17:32:47 +02:00
Michael Krayer 975280a456 Added verbose output 2024-04-02 17:25:42 +02:00
1 changed files with 36 additions and 14 deletions

50
prsync
View File

@ -5,7 +5,7 @@ cat << EOF
A wrapper around rsync which partitions the input files to blocks of roughly A wrapper around rsync which partitions the input files to blocks of roughly
equal sizes and transfers them in multiple streams in parallel. equal sizes and transfers them in multiple streams in parallel.
Usage: $(basename $0) [rsync flags] <num_streams> <src>... <dest> Usage: $(basename $0) [opt] <src>... <dest>
Options: Options:
<num_streams> Number of blocks/transfer streams. <num_streams> Number of blocks/transfer streams.
<src> Source files (potentially multiple files). <src> Source files (potentially multiple files).
@ -14,16 +14,20 @@ Options:
-h, --help Print this message. -h, --help Print this message.
-n, --dry-run Do not transfer any data. -n, --dry-run Do not transfer any data.
-r, --recursive Copy directories recursively -r, --recursive Copy directories recursively
-s, --streams <num> Use <num> parallel streams.
-v, --verbose List files as they are transferred.
EOF EOF
} }
# Parse arguments # Parse arguments
declare -a positional flags_rsync flags_du declare -a positional flags_rsync flags_du
declare -i num_streams=1
positional=() positional=()
flags_rsync=() flags_rsync=('-R' '-v' '--info=stats0,misc0,flist0')
flags_du=('-b') flags_du=('-b')
flag_copy_links=0 flag_copy_links=0
flag_recursive=0 flag_recursive=0
flag_verbose=0
while [[ $# -gt 0 ]]; do while [[ $# -gt 0 ]]; do
case $1 in case $1 in
'-h'|'--help') '-h'|'--help')
@ -47,6 +51,15 @@ while [[ $# -gt 0 ]]; do
flag_recursive=1 flag_recursive=1
shift shift
;; ;;
'-s'|'--streams')
num_streams=$2
shift
shift
;;
'-v'|'--verbose')
flag_verbose=1
shift
;;
-*|--*) -*|--*)
echo "Invalid option: $1" >&2 echo "Invalid option: $1" >&2
exit 1 exit 1
@ -60,13 +73,11 @@ done
declare -i num_args declare -i num_args
num_args=${#positional[@]} num_args=${#positional[@]}
[[ $num_args -lt 3 ]] && usage && exit 1 [[ $num_args -lt 2 ]] && usage && exit 1
# Parse <num_streams> # Parse <num_streams>
declare -i num_streams if [[ $num_streams -lt 1 ]]; then
num_streams=${positional[0]} echo "Error: invalid number of streams" >&2
if [[ $num_streams -eq 0 ]]; then
echo "Error: invalid value for <num_streams> (${positional[0]})" >&2
exit 1 exit 1
fi fi
@ -82,7 +93,7 @@ function walk_dir {
done done
} }
declare -a src declare -a src
for path in "${positional[@]:1:num_args-2}"; do for path in "${positional[@]:0:num_args-1}"; do
if [[ -L ${path} ]] && [[ $flag_copy_links -eq 0 ]]; then if [[ -L ${path} ]] && [[ $flag_copy_links -eq 0 ]]; then
continue continue
elif [[ -f ${path} ]]; then elif [[ -f ${path} ]]; then
@ -110,7 +121,7 @@ src=($(echo "$tmp" | awk '{print $2}'))
totalsize=$(IFS=+; echo "$((${filesize[*]}))") totalsize=$(IFS=+; echo "$((${filesize[*]}))")
# Create file lists # Create file lists
dir_temp=$(mktemp -dt rsync.XXXXX) dir_temp=$(mktemp -dt prsync.XXXXX)
for ((istream=0;istream<num_streams;istream++)); do for ((istream=0;istream<num_streams;istream++)); do
file_temp="${dir_temp}/rsync-stream-${istream}.files" file_temp="${dir_temp}/rsync-stream-${istream}.files"
echo -n > $file_temp echo -n > $file_temp
@ -120,13 +131,16 @@ for ((istream=0;istream<num_streams;istream++)); do
done done
# Transfer data # Transfer data
declare -a rsync_pids declare -a rsync_pids tail_pids
declare -i timer dt_transfer declare -i timer dt_transfer
function rsync_sigint { function rsync_sigint {
echo "Sending SIGINT to remaining streams..." echo "Sending SIGINT to remaining streams..."
for pid in ${rsync_pids[@]}; do for pid in ${rsync_pids[@]}; do
kill -s SIGINT ${pid} kill -s SIGINT ${pid}
done done
for pid in ${tail_pids[@]}; do
kill -s SIGINT ${pid}
done
} }
rsync_pids=() rsync_pids=()
timer=$(date +%s%N) timer=$(date +%s%N)
@ -135,15 +149,23 @@ trap rsync_sigint SIGINT
for ((istream=0;istream<num_streams;istream++)); do for ((istream=0;istream<num_streams;istream++)); do
file_temp="${dir_temp}/rsync-stream-${istream}.files" file_temp="${dir_temp}/rsync-stream-${istream}.files"
file_log="${dir_temp}/rsync-stream-${istream}.log" file_log="${dir_temp}/rsync-stream-${istream}.log"
rsync -v ${flags_rsync[@]} $(cat $file_temp) $dest > $file_log & rsync ${flags_rsync[@]} $(cat $file_temp) $dest > $file_log &
rsync_pids+=($!) rsync_pids+=($!)
if [ $flag_verbose -gt 0 ]; then
tail -F $file_log 2>/dev/null &
tail_pids+=($!)
fi
echo "Started stream #${istream}... pid=${rsync_pids[istream]}, log=${file_log}" echo "Started stream #${istream}... pid=${rsync_pids[istream]}, log=${file_log}"
done done
for pid in ${rsync_pids[@]}; do for ((istream=0;istream<num_streams;istream++)); do
wait $pid wait ${rsync_pids[istream]}
ec_=$? ec_=$?
echo "Process ${pid} finished with exit code $ec_" echo "Process ${rsync_pids[istream]} finished with exit code $ec_"
[[ $ec_ -ne 0 ]] && flag_fail=1 [[ $ec_ -ne 0 ]] && flag_fail=1
if [ $flag_verbose -gt 0 ]; then
kill ${tail_pids[istream]}
wait ${tail_pids[istream]} 2>/dev/null
fi
done done
if [ $flag_fail -ne 0 ]; then if [ $flag_fail -ne 0 ]; then
echo "Transfer failed." echo "Transfer failed."