summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x[-rw-r--r--]rsyncshot47
-rw-r--r--rsyncshot.org114
2 files changed, 93 insertions, 68 deletions
diff --git a/rsyncshot b/rsyncshot
index d12827e..5b01129 100644..100755
--- a/rsyncshot
+++ b/rsyncshot
@@ -1,4 +1,10 @@
#!/bin/bash
+# rsyncshot
+
+# Craig Jennings craigmartinjennings@gmail.com
+# Inspired by Mike Rubel: http://www.mikerubel.org/computers/rsync_snapshots/
+
+# Debugging
# uncomment next 4 lines for debugging output
# exec 5> >(logger -t $0)
@@ -6,6 +12,8 @@
# PS4='$LINENO: '
# set -x
+# Default Locations For Setup
+
SCRIPTLOC=/usr/local/bin/rsyncshot;
DESTINATION=/media/backup;
@@ -15,10 +23,17 @@ LOGHOME=/var/log/rsyncshot.log;
INCLUDES="$INSTALLHOME/include.txt";
EXCLUDES="$INSTALLHOME/exclude.txt";
+# Default Cron Job Entries
+# CRON_H = hourly on minute 0 from 1am to 11pm
+# CRON_D = daily at midnight, Monday - Saturday
+# CRON_W = weekly at midnight on Sundays
+
CRON_H="0 1-23 * * * $SCRIPTLOC hourly 22";
CRON_D="0 0 * * 1-6 $SCRIPTLOC daily 6";
CRON_W="0 0 * * 7 $SCRIPTLOC weekly 51";
+# Help
+
help()
{
echo ""
@@ -33,6 +48,8 @@ help()
echo "Notes:"
echo "- install and log locations defined in script."
+# Error
+
error()
{
echo "ERROR: $0: $@" 1>&2;
@@ -40,6 +57,8 @@ error()
exit 1;
}
+# Setup
+
setup()
{
# copy this file to directory on path
@@ -72,19 +91,31 @@ setup()
echo "hourly, daily, and weekly cron jobs installed.";
}
+# Check Help Option
+
if [ "$TYPE" = "HELP" ]; then help; exit; fi
+# Ensure Root
+
if [ "$EUID" -ne 0 ]; then error "This script must be run as root."; fi
+# Display How Script Was Started
+
echo "rsyncshot invoked on `date -u` with: $0 $1 $2";
+# Parameter Validation
+
if ! [[ $1 =~ [a-zA-Z] ]]; then error "snapshot type not recognized."; fi
TYPE=$(tr '[a-z]' '[A-Z]' <<< $1);
if [ "$TYPE" = "SETUP" ]; then setup; exit; fi
+# Validate Max Snapshots
+
if ! [[ $2 =~ [0-9] ]]; then error "max snapshots not a number."; fi
MAX=$(($2-1));
+# Validate Include File (Source Directories) Exist
+
if [ ! -f "$INCLUDES" ]; then error "include file $INCLUDES not found."; fi
SOURCES=$(<$INCLUDES);
for SOURCE in $SOURCES
@@ -92,8 +123,12 @@ do
if [ ! -d "$SOURCE" ]; then error "source $SOURCE not found"; fi
done
+# Validate Exclude File (Exclusion Patterns) Exist
+
if [ ! -f "$EXCLUDES" ]; then error "Exclude file $EXCLUDES not found."; fi
+# Sync Each Directory In Turn
+
for SOURCE in $SOURCES
do
rsync -avh -i --times \
@@ -102,10 +137,14 @@ do
--update $SOURCE $DESTINATION/latest ;
done
+# Delete Max+1 Snapshot If Exists
+
if [ -d $DESTINATION/$TYPE.$MAX ]; then
rm -rf $DESTINATION/$TYPE.$MAX;
fi
+# Rotate Snapshots Descending
+
for (( start=$(($MAX)); start>=0; start--)); do
end=$(($start+1));
if [ -d $DESTINATION/$TYPE.$start ]; then
@@ -113,11 +152,19 @@ for (( start=$(($MAX)); start>=0; start--)); do
fi
done
+# Reset Directory Timestamp
+
touch $DESTINATION/latest
+# Hard Link Only Copy to Destination
+
cp -al $DESTINATION/latest $DESTINATION/$TYPE.0;
+# Make Directory Type Read-Only
+
chmod -w $DESTINATION/$TYPE.0
+# Print Time and Exit
+
echo "rsyncshot completed `date -u` ";
exit 0;
diff --git a/rsyncshot.org b/rsyncshot.org
index 77797a2..830654b 100644
--- a/rsyncshot.org
+++ b/rsyncshot.org
@@ -1,25 +1,18 @@
* rsyncshot
-:PROPERTIES:
-:COMMENTS: org
-:TANGLE: rsyncshot
-:END:
-Craig Jennings craigmartinjennings@gmail.com
-Inspired by Mike Rubel: http://www.mikerubel.org/computers/rsync_snapshots/
-#+begin_SRC sh :tangle yes
-#!/bin/bash
-#+end_SRC
-** Debugging
-#+begin_SRC sh :tangle yes
+#+begin_SRC sh :tangle rsyncshot :comments org :shebang "#!/bin/bash"
+# Craig Jennings craigmartinjennings@gmail.com
+# Inspired by Mike Rubel: http://www.mikerubel.org/computers/rsync_snapshots/
+#+end_SRC
+* Debugging
+#+begin_SRC sh :tangle rsyncshot :comments org
# uncomment next 4 lines for debugging output
# exec 5> >(logger -t $0)
# BASH_XTRACEFD="5"
# PS4='$LINENO: '
# set -x
#+end_SRC
-** Config
-*** Default Locations
-Default locations for setup
-#+begin_SRC sh :tangle yes
+* Default Locations For Setup
+#+begin_SRC sh :tangle rsyncshot :comments org
SCRIPTLOC=/usr/local/bin/rsyncshot;
DESTINATION=/media/backup;
@@ -29,19 +22,18 @@ LOGHOME=/var/log/rsyncshot.log;
INCLUDES="$INSTALLHOME/include.txt";
EXCLUDES="$INSTALLHOME/exclude.txt";
#+end_SRC
-*** Default Cron Job Entries
-Default cron job entries
+* Default Cron Job Entries
CRON_H = hourly on minute 0 from 1am to 11pm
CRON_D = daily at midnight, Monday - Saturday
CRON_W = weekly at midnight on Sundays
-#+begin_SRC sh :tangle yes
+#+begin_SRC sh :tangle rsyncshot :comments org
CRON_H="0 1-23 * * * $SCRIPTLOC hourly 22";
CRON_D="0 0 * * 1-6 $SCRIPTLOC daily 6";
CRON_W="0 0 * * 7 $SCRIPTLOC weekly 51";
#+end_SRC
-** Functions
-*** Help
-#+begin_SRC sh :tangle yes
+* Functions
+** Help
+#+begin_SRC sh :tangle rsyncshot :comments org
help()
{
echo ""
@@ -57,8 +49,8 @@ help()
echo "- install and log locations defined in script."
#+end_SRC
-*** Error
-#+begin_SRC sh :tangle yes
+** Error
+#+begin_SRC sh :tangle rsyncshot :comments org
error()
{
echo "ERROR: $0: $@" 1>&2;
@@ -66,8 +58,8 @@ error()
exit 1;
}
#+end_SRC
-*** Setup
-#+begin_SRC sh :tangle yes
+** Setup
+#+begin_SRC sh :tangle rsyncshot :comments org
setup()
{
# copy this file to directory on path
@@ -100,38 +92,32 @@ setup()
echo "hourly, daily, and weekly cron jobs installed.";
}
#+end_SRC
-** Script
-*** Check Help Option
-If user requested help, display and exit
-#+begin_SRC sh :tangle yes
+
+* Check Help Option
+#+begin_SRC sh :tangle rsyncshot :comments org
if [ "$TYPE" = "HELP" ]; then help; exit; fi
#+end_SRC
-*** Ensure Root
-Ensure we're running as root
-#+begin_SRC sh :tangle yes
+* Ensure Root
+#+begin_SRC sh :tangle rsyncshot :comments org
if [ "$EUID" -ne 0 ]; then error "This script must be run as root."; fi
#+end_SRC
-*** Display How Script Was Started
-Display how the script was started
-#+begin_SRC sh :tangle yes
+* Display How Script Was Started
+#+begin_SRC sh :tangle rsyncshot :comments org
echo "rsyncshot invoked on `date -u` with: $0 $1 $2";
#+end_SRC
-*** Parameter Validation
-Validate first arg is alpha chars and make it case insensitive. If user requested setup, call function and exit.
-#+begin_SRC sh :tangle yes
+* Parameter Validation
+#+begin_SRC sh :tangle rsyncshot :comments org
if ! [[ $1 =~ [a-zA-Z] ]]; then error "snapshot type not recognized."; fi
TYPE=$(tr '[a-z]' '[A-Z]' <<< $1);
if [ "$TYPE" = "SETUP" ]; then setup; exit; fi
#+end_SRC
-*** Validate Max Snapshots
-Validate second arg (max snapshots) is numeric.
-#+begin_SRC sh :tangle yes
+* Validate Max Snapshots
+#+begin_SRC sh :tangle rsyncshot :comments org
if ! [[ $2 =~ [0-9] ]]; then error "max snapshots not a number."; fi
MAX=$(($2-1));
#+end_SRC
-*** Validate Include File
-Validate include file (source directories)
-#+begin_SRC sh :tangle yes
+* Validate Include File (Source Directories) Exist
+#+begin_SRC sh :tangle rsyncshot :comments org
if [ ! -f "$INCLUDES" ]; then error "include file $INCLUDES not found."; fi
SOURCES=$(<$INCLUDES);
for SOURCE in $SOURCES
@@ -139,15 +125,13 @@ do
if [ ! -d "$SOURCE" ]; then error "source $SOURCE not found"; fi
done
#+end_SRC
-*** Validate Exclude File
-Validate exclude file (exclusion patterns)
-#+begin_SRC sh :tangle yes
+* Validate Exclude File (Exclusion Patterns) Exist
+#+begin_SRC sh :tangle rsyncshot :comments org
if [ ! -f "$EXCLUDES" ]; then error "Exclude file $EXCLUDES not found."; fi
#+end_SRC
-*** Sync
-Perform the sync, each directory in turn
-#+begin_SRC sh :tangle yes
+* Sync Each Directory In Turn
+#+begin_SRC sh :tangle rsyncshot :comments org
for SOURCE in $SOURCES
do
rsync -avh -i --times \
@@ -156,16 +140,14 @@ do
--update $SOURCE $DESTINATION/latest ;
done
#+end_SRC
-*** Delete Old Snapshot
-Delete the snapshot to go over max
-#+begin_SRC sh :tangle yes
+* Delete Max+1 Snapshot If Exists
+#+begin_SRC sh :tangle rsyncshot :comments org
if [ -d $DESTINATION/$TYPE.$MAX ]; then
rm -rf $DESTINATION/$TYPE.$MAX;
fi
#+end_SRC
-*** Rotate Snapshots
-Rotate snapshots descending
-#+begin_SRC sh :tangle yes
+* Rotate Snapshots Descending
+#+begin_SRC sh :tangle rsyncshot :comments org
for (( start=$(($MAX)); start>=0; start--)); do
end=$(($start+1));
if [ -d $DESTINATION/$TYPE.$start ]; then
@@ -173,24 +155,20 @@ for (( start=$(($MAX)); start>=0; start--)); do
fi
done
#+end_SRC
-*** Set Directory Timestamp
-Touch the directory for a timestamp
-#+begin_SRC sh :tangle yes
+* Reset Directory Timestamp
+#+begin_SRC sh :tangle rsyncshot :comments org
touch $DESTINATION/latest
#+end_SRC
-*** Hard Link to Destination
-Make a hard-link-only copy into $TYPE.0
-#+begin_SRC sh :tangle yes
+* Hard Link Only Copy to Destination
+#+begin_SRC sh :tangle rsyncshot :comments org
cp -al $DESTINATION/latest $DESTINATION/$TYPE.0;
#+end_SRC
-*** Make Directory Type Read-Only
-Make the directory $TYPE.0 read-only
-#+begin_SRC sh :tangle yes
+* Make Directory Type Read-Only
+#+begin_SRC sh :tangle rsyncshot :comments org
chmod -w $DESTINATION/$TYPE.0
#+end_SRC
-*** Print Time and Exit
-Print end time and exit
-#+begin_SRC sh :tangle yes
+* Print Time and Exit
+#+begin_SRC sh :tangle rsyncshot :comments org
echo "rsyncshot completed `date -u` ";
exit 0;
#+end_SRC