-
-
Save yabasha/a9547862e4fdd4073bb616d9564e27e8 to your computer and use it in GitHub Desktop.
Shell script to handle incremental data backups with rsync. Optimised to handle large number of infrequently changing files, by using hard links to save on used disk space. For more details - http://localhost:4000/2014/01/12/automatic-backups-with-ruby-and-linux-shell-part-3/
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 | |
# Rsync based file backup script, with hard-linking enabled. | |
# | |
# Runtime options: | |
# -n - dry-run; do nothing, just display what is going to happen on a real run | |
# -v - verbose output; print out what is being backed up | |
# | |
# set to your rsync location | |
RSYNC_BIN="/usr/bin/rsync" | |
# location of the files to back up (WITH a trailing slash) | |
SOURCE_DIR="/path/to/source_dir/" | |
# target dir for backups (NO trailing slash) | |
BACKUP_DIR="/path/to/backup_dir" | |
# how many backups to keep | |
KEEP_BACKUPS=7 | |
# | |
# END OF CONFIGURATION | |
# | |
# takes command to execute as the first argument, and then | |
# 1. Prints it if we're in verbose mode | |
# 2. If we're in dry-run mode, as the second argument is nil - does nothing | |
# 3. If we're not in dry-run mode - executes the command | |
# 4. If we're in dry-run mode, but the 2nd argument is not nill - executes the commad | |
# (i.e. when it's constructed to dry-run by itself) | |
function docmd { | |
if [ "$verbose" -eq 1 ]; then echo "--- $1"; fi | |
# if [ [ "$dry_run" -eq 0 ] -o [ -n $2 ] ]; then `$1`; fi | |
if [ "$dry_run" -eq 0 ] || [ -n "$2" ]; then $1; fi | |
} | |
# reset getopts | |
OPTIND=1 | |
# set default values for configuration params | |
dry_run=0 | |
verbose=0 | |
while getopts "vn" opt; do | |
case "$opt" in | |
v) verbose=1; | |
;; | |
n) dry_run=1; verbose=1; | |
;; | |
esac | |
done | |
# generate directory name that we'll be syncing into | |
timestamp=`date +"%Y.%m.%d.%H.%M.%S"` | |
sync_target="$BACKUP_DIR/$timestamp" | |
# extra rsync options | |
rsync_options="" | |
# get a directory to link against, if any | |
link_target=`ls -1 $BACKUP_DIR | tail -n1` | |
# if we have a valid link directory - set it as an option for rsync | |
if [ -n "$link_target" ]; then rsync_options="--link-dest=$BACKUP_DIR/$link_target"; fi | |
# if we're in verbose mode - set it for rsync | |
if [ "$verbose" -eq 1 ]; then rsync_options="$rsync_options -v"; fi | |
# if we're in dry run mode - set it for rsync | |
if [ "$dry_run" -eq 1 ]; then rsync_options="$rsync_options -n"; fi | |
docmd "mkdir -p $sync_target" | |
docmd "$RSYNC_BIN -a --delete $rsync_options $SOURCE_DIR $sync_target" 1 | |
backups_count=`ls -1 $BACKUP_DIR | wc -l` | |
backups_to_remove=$(($backups_count-$KEEP_BACKUPS)) | |
if [ $backups_to_remove -gt 0 ]; then | |
for d in `ls -1 $BACKUP_DIR | head -n$backups_to_remove`; do | |
docmd "rm -rf $BACKUP_DIR/$d" | |
done | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment