david/sshbackup
david
/
sshbackup
Archived
1
0
Fork 0
This repository has been archived on 2023-12-23. You can view files and clone it, but cannot push or open issues or pull requests.
sshbackup/sshbackup

286 lines
7.2 KiB
Bash
Executable File

#!/bin/bash
# ************************************* #
# #
# sshbackup #
# #
# ************************************* #
# **** config section ****
version="0.3.1"
author="david@socialnerds.org"
configfile="$HOME/.sshbackup"
#rsync options.
rsyncoptions="-pogEthrzl --numeric-ids --no-motd"
#dotglob option removes bug while rsyncing folder with no visible files in it.
remotecmd="shopt -s dotglob; /usr/bin/sudo /usr/bin/rsync"
localcmd="/usr/bin/rsync"
sshkeyfile="$HOME/.ssh/id_rsa"
versions=999
config=0
sshkey=0
list=0
options=$*
# **** function definitions ****
bashtrap()
{
echo
echo "CTRL+C detected."
echo "commiting suicide."
exit 1
}
usage()
{
echo
echo "usage: sshbackup <options> source destination [versions]"
echo "source/destination example: [[user@]server:]/path/to/files"
echo
echo "OPTIONS:"
echo " -h, --help show this message"
echo " -v, --version version information"
echo
echo " -c, --config <file> alternate config file [~/.sshbackup]"
echo " -l, --list <file> list of sources and destinations"
echo " -s, --sshkey <file> alternate sshkey [~/.ssh/id_rsa]"
echo
}
version()
{
echo
echo -e "vesion: \033[1;37m$version\033[0m"
echo "author: $author"
echo
}
preflight()
{
#amiroot?
if [ $(whoami) != "root" ]; then
echo "aborting mission. you must be root."
return 1
fi
#source and destination path?
if [ -z $sourcepath ]; then
echo "aborting mission. no source path given."
return 1
elif [ -z $destinationpath ]; then
echo "aborting mission. no destination path given."
return 1
fi
#if remote source or destination check for sshkey
if [[ $sourcepath =~ .*@.* ]] || [[ $destinationpath =~ .*@.* ]]; then
if [ -r $sshkeyfile ]; then
#echo "sshkeyfile found. continuing."
:
else
echo "aborting mission. no sshkey found."
return 1
fi
fi
return 0
}
sshbackup()
{
#creating local rsync options var
local cmdopt="$rsyncoptions"
#move existing versions
local num=$versions
while [ -d "$destinationpath/0" ]; do
if [ -d "$destinationpath/$num" ]; then
mv $destinationpath/$num $destinationpath/$((num+1))
fi
let num--
done
#create destinationpath if not existing
mkdir -p $destinationpath/0
#add link-destination option if existing
if [ -d $destinationpath/1 ]; then
cmdopt="$cmdopt --link-dest=$destinationpath/1"
fi
#run rsync
$localcmd $cmdopt -e "ssh -q -i $sshkeyfile" --rsync-path="$remotecmd" $sourcepath $destinationpath/0
if [ $? -ne "0" ]; then
return 1
fi
#removing obsolet version(s)
local i=1
while [ -d $destinationpath/$((versions+i)) ]; do
rm -rf $destinationpath/$((versions+i))
let i++
done
return 0
}
# **** start of script ****
#initialize bashtrap
trap bashtrap INT
# **** option handler ****
if [ -z $1 ]; then
usage
exit 0
fi
for option in $options; do
case "$option" in
-h|--help)
usage
exit 0
;;
-v|--version)
version
exit 0
;;
-c|--config)
config=1
;;
-l|--list)
list=1
;;
-s|--sshkey)
sshkey=1
;;
*)
if [ $config -eq 1 ]; then
if [ -r "$option" ]; then
configfile=$option
config=0
else
echo "aborting mission. cannot read configfile. [$option]"
exit 1
fi
elif [ $sshkey -eq 1 ]; then
if [ -r $option ]; then
sshkeyfile=$option
sshkey=0
else
echo "aborting mission. cannot read sshkeyfile. [$option]"
exit 1
fi
elif [ $list -eq 1 ]; then
if [ -r $option ]; then
listfile=$option
list=0
else
echo "aborting mission. cannot read listfile. [$option]"
exit 1
fi
else
if [[ $option =~ ^-.* ]]; then
echo "aborting mission. unknown option given. [$option]"
usage
exit 1
#TODO: what if source or destination is a number?
elif [ -z "${option//[0-9]/}" ]; then
versions="$option"
else
if [ -z "$sourcepath" ]; then
if [[ $option =~ .*@.* ]]; then
sourcepath="${option%/}/"
elif [[ $option =~ ^/.* ]]; then
sourcepath="${option%/}/"
else
sourcepath="$(pwd)/${option%/}/"
fi
else
if [ -z "$destinationpath" ]; then
if [[ $option =~ ^/.* ]]; then
destinationpath="${option%/}"
else
destinationpath="$(pwd)/${option%/}"
fi
fi
fi
fi
fi
;;
esac
done
if [ -r "$configfile" ]; then
source "$configfile"
fi
#read list if listfile is given
if [ -r "$listfile" ]; then
while read line; do
# find first letter
fletter=${line:0:1}
if [ -z $fletter ]; then
#skip line it's empty
:
elif [ $fletter = "#" ]; then
#skip line it's a comment
:
else
sourcepath=""
destinationpath=""
for option in $line; do
if [ -z "${option//[0-9]/}" ]; then
versions="$option"
else
if [ -z "$sourcepath" ]; then
if [[ $option =~ .*@.* ]]; then
sourcepath="${option%/}/"
elif [[ $option =~ ^/.* ]]; then
sourcepath="${option%/}/"
else
sourcepath="$(pwd)/${option%/}/"
fi
else
if [ -z "$destinationpath" ]; then
if [[ $option =~ ^/.* ]]; then
destinationpath="${option%/}"
else
destinationpath="$(pwd)/${option%/}"
fi
fi
fi
fi
done
if ( preflight ); then
sshbackup
fi
fi
done < "$listfile"
else
if ( preflight ); then
sshbackup
fi
fi
# **** end of script ****
exit 0