Script to backup a folder and also be able to maintain several previous versions efficiently
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

146 lines
3.1KB

  1. #!/bin/bash
  2. # ---------------------------
  3. # Filesystem Snapshot Utility
  4. # Micah Halter
  5. # ---------------------------
  6. #--System Commands--
  7. ID=/usr/bin/id;
  8. ECHO=/bin/echo;
  9. MOUNT=/bin/mount;
  10. UMOUNT=/bin/umount;
  11. RM=/bin/rm;
  12. MV=my_mv;
  13. CP=/bin/cp;
  14. TOUCH=/bin/touch;
  15. SUDO=/usr/bin/sudo;
  16. RSYNC=/usr/bin/rsync;
  17. #Redefines mv to fix the changing timestamp issue on backups
  18. #Allows you to move a backup while maintaining the original timestamp
  19. my_mv() {
  20. REF=/tmp/makesnapshot-mymv-$$;
  21. touch -r $1 $REF;
  22. /bin/mv $1 $2;
  23. touch -r $REF $2;
  24. /bin/rm $REF;
  25. }
  26. showusage() {
  27. echo "Usage:"
  28. echo " backup [options] source destination"
  29. echo ""
  30. echo "Options:"
  31. echo " -d <drive> A drive to be mounted to destination before creating snapshot of source"
  32. echo " -n <num> How many backups should be kept of source in destination (default: 3)"
  33. echo " -h Show this screen."
  34. }
  35. NUM=3
  36. while getopts "n:d:h" opt; do
  37. case ${opt} in
  38. d )
  39. DRIVE="$OPTARG"
  40. ;;
  41. n )
  42. NUM="$OPTARG"
  43. if ! [ "$NUM" -eq "$NUM" ] 2>/dev/null; then
  44. echo "$NUM is not a number"
  45. showusage
  46. exit 1
  47. elif [ $NUM -lt 1 ]; then
  48. echo "There must be at least 1 backup"
  49. showusage
  50. exit 1
  51. fi
  52. ;;
  53. h )
  54. showusage
  55. exit 0
  56. ;;
  57. \? )
  58. echo "Invalid Option: -$OPTARG" 1>&2
  59. showusage
  60. exit 1
  61. ;;
  62. esac
  63. done
  64. shift $((OPTIND - 1))
  65. SOURCE=$1
  66. OUTPUT=$2
  67. if [[ -z "$1" || -z "$2" ]]; then
  68. showusage
  69. exit 1
  70. fi
  71. #--Mount Drive RW--
  72. if [ ! -z "$DRIVE" ]; then
  73. #Use umount and mount instead of remount because of ntfs
  74. #filesystem limitations
  75. $SUDO $UMOUNT $DRIVE ;
  76. $SUDO $MOUNT $DRIVE -o rw ;
  77. if (( $? )); then {
  78. $ECHO "snapshot: chould not remount $DRIVE readwrite";
  79. exit;
  80. } fi ;
  81. fi
  82. #--Snapshot Script--
  83. if [ ! -d $SOURCE ]; then
  84. echo "$SOURCE does not exist"
  85. exit 1
  86. fi
  87. if [ ! -d $OUTPUT ]; then
  88. echo "$OUTPUT does not exist"
  89. exit 1
  90. fi
  91. ((NUM--))
  92. # 1 - Delete oldest snapshot, if it exists:
  93. if [ -d $OUTPUT/snapshot.$NUM ] ; then
  94. #moving file and use of the '&' at the end
  95. #runs the command in the background so you
  96. #don't have to wait for the old folder to delete
  97. $MV $OUTPUT/snapshot.$NUM $OUTPUT/snapshot.tmp
  98. $RM -rf $OUTPUT/snapshot.tmp&
  99. fi ;
  100. # 2 - Shift middle snapshots back one:
  101. while (( NUM > 1 )); do
  102. old=$NUM
  103. ((NUM--))
  104. if [ -d $OUTPUT/snapshot.$NUM ] ; then
  105. $MV $OUTPUT/snapshot.$NUM $OUTPUT/snapshot.$old ;
  106. fi ;
  107. done
  108. # 3 - Make hard-link-only copy of latest snapshot, if it exists:
  109. if [[ $NUM -gt 0 && -d $OUTPUT/snapshot.0 ]] ; then
  110. $CP -al $OUTPUT/snapshot.0 $OUTPUT/snapshot.1;
  111. fi ;
  112. # 4 - Rsync system to new snapshot
  113. $RSYNC -va --delete $SOURCE/ $OUTPUT/snapshot.0 ;
  114. # 5 - Update the timestamp of latest snapshot to reflect backup time
  115. $TOUCH $OUTPUT/snapshot.0 ;
  116. #--Remount drive readonly--
  117. #Use umount and mount instead of remount because of ntfs
  118. #filesystem limitations
  119. if [ ! -z "$DRIVE" ]; then
  120. $SUDO $UMOUNT $DRIVE ;
  121. $SUDO $MOUNT $DRIVE -o ro ;
  122. if (( $? )); then {
  123. $ECHO "snapshot: chould not remount $OUTPUT readonly";
  124. exit;
  125. } fi ;
  126. fi