2013-04-28 16:00:22 +02:00
|
|
|
#!/bin/bash
|
2013-04-27 21:00:51 +02:00
|
|
|
|
|
|
|
# ************************************* #
|
|
|
|
# #
|
|
|
|
# sshbackup #
|
|
|
|
# #
|
|
|
|
# ************************************* #
|
|
|
|
|
|
|
|
# **** config section ****
|
2013-07-01 10:56:28 +02:00
|
|
|
version="0.4.0"
|
2013-04-27 21:00:51 +02:00
|
|
|
author="david@socialnerds.org"
|
|
|
|
|
|
|
|
configfile="$HOME/.sshbackup"
|
|
|
|
#rsync options.
|
2013-04-28 18:18:58 +02:00
|
|
|
rsyncoptions="-qpogEthrzl --numeric-ids --no-motd"
|
2013-04-27 21:00:51 +02:00
|
|
|
#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 " -l, --list <file> list of sources and destinations"
|
2013-04-30 16:46:19 +02:00
|
|
|
echo " -c, --config <file> alternate config file [~/.sshbackup]"
|
2013-04-27 21:00:51 +02:00
|
|
|
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
|
2013-07-01 15:38:01 +02:00
|
|
|
}
|
2013-04-27 21:00:51 +02:00
|
|
|
|
2013-07-01 15:38:01 +02:00
|
|
|
interactive()
|
|
|
|
{
|
|
|
|
tty -s
|
|
|
|
return $?
|
2013-04-27 21:00:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
2013-04-28 23:36:22 +02:00
|
|
|
elif [ -z $destpath ]; then
|
2013-04-27 21:00:51 +02:00
|
|
|
echo "aborting mission. no destination path given."
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
|
2013-07-01 15:38:01 +02:00
|
|
|
#if remote source or destination check for ssh key
|
2013-04-28 23:36:22 +02:00
|
|
|
if [[ $sourcepath =~ .*@.* ]] || [[ $destpath =~ .*@.* ]]; then
|
2013-07-01 15:38:01 +02:00
|
|
|
#if [ -r $sshkeyfile ]; then
|
|
|
|
# #echo "sshkeyfile found. continuing."
|
|
|
|
# :
|
|
|
|
#else
|
|
|
|
# echo "aborting mission. no sshkey found."
|
|
|
|
# return 1
|
|
|
|
#fi
|
|
|
|
keymgmt $sshkeyfile
|
2013-04-27 21:00:51 +02:00
|
|
|
fi
|
|
|
|
|
|
|
|
return 0
|
2013-07-01 15:38:01 +02:00
|
|
|
}
|
2013-04-27 21:00:51 +02:00
|
|
|
|
2013-07-01 15:38:01 +02:00
|
|
|
keymgmt()
|
|
|
|
{
|
|
|
|
local username=$(id -un)
|
|
|
|
local userid=$(id -u)
|
|
|
|
|
|
|
|
#find out where running 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
|
2013-04-27 21:00:51 +02:00
|
|
|
|
2013-07-01 15:38:01 +02:00
|
|
|
if [ -z $1 ]; then
|
|
|
|
sshkeyfile="$home/.ssh/id_rsa"
|
|
|
|
else
|
|
|
|
sshkeyfile="$1"
|
|
|
|
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."
|
|
|
|
exit 1
|
|
|
|
elif [ $choice == "y" ] || [ $choice == "Y" ]; then
|
|
|
|
#creating ssh key pair
|
|
|
|
ssh-keygen
|
|
|
|
fi
|
|
|
|
else
|
|
|
|
echo "aborting mission. no ssh key found."
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
fi
|
2013-04-27 21:00:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
sshbackup()
|
|
|
|
{
|
|
|
|
#creating local rsync options var
|
|
|
|
local cmdopt="$rsyncoptions"
|
|
|
|
|
|
|
|
#move existing versions
|
|
|
|
local num=$versions
|
2013-04-28 23:36:22 +02:00
|
|
|
while [ -d "$destpath/0" ]; do
|
|
|
|
if [ -d "$destpath/$num" ]; then
|
|
|
|
mv $destpath/$num $destpath/$((num+1))
|
2013-04-27 21:00:51 +02:00
|
|
|
fi
|
|
|
|
let num--
|
|
|
|
done
|
|
|
|
|
2013-04-28 23:36:22 +02:00
|
|
|
#create destpath if not existing
|
|
|
|
mkdir -p $destpath/0
|
2013-04-27 21:00:51 +02:00
|
|
|
|
|
|
|
#add link-destination option if existing
|
2013-04-28 23:36:22 +02:00
|
|
|
if [ -d $destpath/1 ]; then
|
|
|
|
cmdopt="$cmdopt --link-dest=$destpath/1"
|
2013-04-27 21:00:51 +02:00
|
|
|
fi
|
|
|
|
|
|
|
|
#run rsync
|
2013-04-28 23:36:22 +02:00
|
|
|
$localcmd $cmdopt -e "ssh -q -i $sshkeyfile" --rsync-path="$remotecmd" $sourcepath $destpath/0
|
2013-04-27 21:00:51 +02:00
|
|
|
if [ $? -ne "0" ]; then
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
#removing obsolet version(s)
|
|
|
|
local i=1
|
2013-04-28 23:36:22 +02:00
|
|
|
while [ -d $destpath/$((versions+i)) ]; do
|
|
|
|
rm -rf $destpath/$((versions+i))
|
2013-04-27 21:00:51 +02:00
|
|
|
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
|
2013-04-28 17:02:16 +02:00
|
|
|
sourcepath="${option%/}/*"
|
2013-04-27 21:00:51 +02:00
|
|
|
elif [[ $option =~ ^/.* ]]; then
|
2013-04-28 17:02:16 +02:00
|
|
|
sourcepath="${option%/}/*"
|
2013-04-27 21:00:51 +02:00
|
|
|
else
|
2013-04-28 17:02:16 +02:00
|
|
|
sourcepath="$(pwd)/${option%/}/*"
|
2013-04-27 21:00:51 +02:00
|
|
|
fi
|
|
|
|
else
|
2013-04-28 23:36:22 +02:00
|
|
|
if [ -z "$destpath" ]; then
|
2013-04-27 21:00:51 +02:00
|
|
|
if [[ $option =~ ^/.* ]]; then
|
2013-04-28 23:36:22 +02:00
|
|
|
destpath="${option%/}"
|
2013-04-27 21:00:51 +02:00
|
|
|
else
|
2013-04-28 23:36:22 +02:00
|
|
|
destpath="$(pwd)/${option%/}"
|
2013-04-27 21:00:51 +02:00
|
|
|
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=""
|
2013-04-28 23:36:22 +02:00
|
|
|
destpath=""
|
2013-04-27 21:00:51 +02:00
|
|
|
for option in $line; do
|
|
|
|
if [ -z "${option//[0-9]/}" ]; then
|
|
|
|
versions="$option"
|
|
|
|
else
|
|
|
|
if [ -z "$sourcepath" ]; then
|
|
|
|
if [[ $option =~ .*@.* ]]; then
|
2013-04-28 17:02:16 +02:00
|
|
|
sourcepath="${option%/}/*"
|
2013-04-27 21:00:51 +02:00
|
|
|
elif [[ $option =~ ^/.* ]]; then
|
2013-04-28 17:02:16 +02:00
|
|
|
sourcepath="${option%/}/*"
|
2013-04-27 21:00:51 +02:00
|
|
|
else
|
2013-04-28 17:02:16 +02:00
|
|
|
sourcepath="$(pwd)/${option%/}/*"
|
2013-04-27 21:00:51 +02:00
|
|
|
fi
|
|
|
|
else
|
2013-04-28 23:36:22 +02:00
|
|
|
if [ -z "$destpath" ]; then
|
2013-04-27 21:00:51 +02:00
|
|
|
if [[ $option =~ ^/.* ]]; then
|
2013-04-28 23:36:22 +02:00
|
|
|
destpath="${option%/}"
|
2013-04-27 21:00:51 +02:00
|
|
|
else
|
2013-04-28 23:36:22 +02:00
|
|
|
destpath="$(pwd)/${option%/}"
|
2013-04-27 21:00:51 +02:00
|
|
|
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
|