Advertisement
devinteske

multiprogress.sh

Feb 1st, 2017
533
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 3.10 KB | None | 0 0
  1. #!/bin/sh
  2. # vi: set filetype=sh
  3. ############################################################ CONFIGURATION
  4.  
  5. #
  6. # File to send
  7. #
  8. FILE="5GB"
  9.  
  10. #
  11. # Size of test file to create
  12. # NB: Comment-out to disable (e.g., if $FILE is a real file you want to send)
  13. #
  14. TESTSIZE_IN_MB=$(( 5 * 1024 ))
  15.  
  16. #
  17. # scp(1) destination
  18. # NB: Can contain destination name for $FILE
  19. # NB: Keyword `CURRENT_HOST' replaced with destination hostname
  20. #
  21. DEST="localhost:$FILE.CURRENT_HOST"
  22.  
  23. #
  24. # List of hosts to send the file to
  25. #
  26. HOSTS="sa saro cc bob"
  27.  
  28. #
  29. # Maximum number of copies to perform in parallel
  30. #
  31. MAX_PARALLEL=2
  32.  
  33. ############################################################ GLOBALS
  34.  
  35. #
  36. # Process ID for backgrounded xargs(1) process
  37. #
  38. XARGS_PID=
  39.  
  40. ############################################################ FUNCTIONS
  41.  
  42. cleanup()
  43. {
  44.     local retval=$? host log pid
  45.     echo
  46.     kill "$XARGS_PID" > /dev/null 2>&1
  47.     for host in $HOSTS; do
  48.         log="file_$host"
  49.         pid=$( head -1 "$log" 2> /dev/null )
  50.         kill "$pid" > /dev/null 2>&1
  51.         rm -f "$log"
  52.     done
  53.     exit $retval
  54. }
  55.  
  56. ############################################################ MAIN
  57.  
  58. trap cleanup INT
  59.  
  60. #
  61. # Generate the test payload if necessary/possible
  62. #
  63. if [ "$TESTSIZE_IN_MB" -a ! -e "$FILE" ]; then
  64.     echo "Creating $FILE... (this may take a while)"
  65.     dd if=/dev/urandom of="$FILE" bs=1m count="$TESTSIZE_IN_MB" || exit
  66. elif [ ! -e "$FILE" ]; then
  67.     echo "$FILE: No such file or directory" >&2
  68.     exit 1
  69. elif [ -d "$FILE" ]; then
  70.     echo "$FILE: Is a directory" >&2
  71.     exit 1
  72. fi
  73.  
  74. #
  75. # Cleanup any logfiles left from previous runs
  76. #
  77. for host in $HOSTS; do
  78.     rm -f "file_$host"
  79. done
  80.  
  81. #
  82. # Send the payload to multiple hosts in parallel whilst logging progress
  83. #
  84. echo $HOSTS | xargs -rn1 -ICURRENT_HOST -P$MAX_PARALLEL \
  85.     script -aqt0 file_CURRENT_HOST sh -c '
  86.     file="$1"
  87.     dest="$2"
  88.     log="$3"
  89.     cleanup()
  90.     {
  91.         echo RET:$? >> "$log"
  92.     }
  93.     echo $$ > "$log"
  94.     trap cleanup EXIT
  95.     scp "$file" "$dest"
  96. ' /bin/sh "$FILE" "$DEST" file_CURRENT_HOST > /dev/null 2>&1 &
  97. XARGS_PID=$!
  98.  
  99. #
  100. # To display progress from multiple copies
  101. #
  102. while :; do
  103.     status=
  104.     all_done=1
  105.     for host in $HOSTS; do
  106.         log="file_$host"
  107.         state=pend
  108.         running=
  109.         if [ -e "$log" ]; then
  110.             pct=
  111.             state=fail
  112.             pid=$( head -1 "$log" 2> /dev/null )
  113.             kill -0 "$pid" > /dev/null 2>&1 && running=1
  114.         else
  115.             all_done=
  116.         fi
  117.         if [ "$running" ]; then
  118.             _pct=$( awk 'END {
  119.                 sub(/\r+$/, "")
  120.                 sub(/.*\r/, "")
  121.                 if (match($0, /[[:digit:]]+%/))
  122.                     print substr($0, RSTART, RLENGTH-1)
  123.             }' "$log" 2> /dev/null )
  124.             pct=${_pct:-$pct}
  125.             state="${pct:-0}%"
  126.             all_done=
  127.         elif _ret=$( awk 'END {
  128.             if (sub(/^RET:/, "")) {
  129.                 print
  130.                 exit 0
  131.             }
  132.             exit 1
  133.         }' "$log" 2> /dev/null ); then
  134.             pct=
  135.             state=done
  136.             [ $_ret -ne 0 ] && state=fail
  137.         fi
  138.         status="$status $( printf "%s [%4s]" $host $state )"
  139.     done
  140.     printf "\r%s\t\t%s" "$( date )" "$status"
  141.     [ "$all_done" ] && break
  142.     sleep 1
  143. done
  144. echo
  145.  
  146. ################################################################################
  147. # END
  148. ################################################################################
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement