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

321 lines
8.3 KiB
Bash
Executable File

#!/bin/bash
# ************************************* #
# #
# sshbackup #
# #
# ************************************* #
# **** config section ****
version="0.4.0"
author="david@socialnerds.org"
configfile="$HOME/.sshbackup"
#rsync options.
rsyncoptions="-qpogEthrzl --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"
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 " -l, --list <file> list of sources and destinations"
echo " -c, --config <file> alternate config file [~/.sshbackup]"
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
}
interactive()
{
tty -s
return $?
}
amiroot()
{
if [ $(id -u) -eq 0 ]; then
return 0
else
return 1
fi
}
preflight()
{
#amiroot?
if ( ! amiroot ); 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 $destpath ]; then
echo "aborting mission. no destination path given."
return 1
fi
#if there is a remote source or destination check for ssh key
if [[ $sourcepath =~ .*@.* ]] || [[ $destpath =~ .*@.* ]]; then
#get executing user id
local userid=$(id -u)
#find out where executing users $HOME is
while read line; do
line=$(echo $line | sed 's/ //g')
line=$(echo $line | sed 's/:/ /g')
if [ $(echo $line | awk '{print $3}') -eq $userid ]; then
local home=$(echo $line | awk '{print $6}')
fi
done < /etc/passwd
if [ -z $sshkeyfile ]; then
sshkeyfile="$home/.ssh/id_rsa"
fi
if [ -r $sshkeyfile ]; then
#ssh key found
:
else
if ( interactive ); then
echo "no ssh key found"
echo -e "do you want to create a ssh key pair? [y/n] \c"
read choice
if [ -z $choice ]; then
echo "aborting mission. no ssh key found."
return 1
elif [ $choice == "y" ] || [ $choice == "Y" ]; then
#creating ssh key pair
ssh-keygen
#TODO: key should also be deployed to remote side
return 1 #for now i'll break up here
fi
else
echo "aborting mission. no ssh key found."
return 1
fi
fi
fi
return 0
}
sshbackup()
{
#creating local rsync options var
local cmdopt="$rsyncoptions"
#move existing versions
local num=$versions
while [ -d "$destpath/0" ]; do
if [ -d "$destpath/$num" ]; then
mv $destpath/$num $destpath/$((num+1))
fi
let num--
done
#create destpath if not existing
mkdir -p $destpath/0
#add link-destination option if existing
if [ -d $destpath/1 ]; then
cmdopt="$cmdopt --link-dest=$destpath/1"
fi
#run rsync
$localcmd $cmdopt -e "ssh -q -i $sshkeyfile" --rsync-path="$remotecmd" $sourcepath $destpath/0
if [ $? -ne "0" ]; then
return 1
fi
#removing obsolet version(s)
local i=1
while [ -d $destpath/$((versions+i)) ]; do
rm -rf $destpath/$((versions+i))
let i++
done
return 0
}
# **** start of script ****
#initialize bashtrap
trap bashtrap INT
# **** option handler ****
#end script if no options are given
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 "$destpath" ]; then
if [[ $option =~ ^/.* ]]; then
destpath="${option%/}"
else
destpath="$(pwd)/${option%/}"
fi
fi
fi
fi
fi
;;
esac
done
#read config if there is one
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=""
destpath=""
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 "$destpath" ]; then
if [[ $option =~ ^/.* ]]; then
destpath="${option%/}"
else
destpath="$(pwd)/${option%/}"
fi
fi
fi
fi
done
if ( preflight ); then
sshbackup
fi
fi
done < "$listfile"
else
if ( preflight ); then
sshbackup
fi
fi
exit 0
# **** end of script ****