aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/changelog4
-rw-r--r--handlers/easydialog.sh7
-rw-r--r--handlers/rdiff147
-rw-r--r--handlers/rdiff.helper141
-rwxr-xr-xninjahelper4
5 files changed, 195 insertions, 108 deletions
diff --git a/docs/changelog b/docs/changelog
index 50a12ef..feef624 100644
--- a/docs/changelog
+++ b/docs/changelog
@@ -1,4 +1,4 @@
-version 0.9 -- unreleased
+version 0.9 -- October 19 2005
*** IMPORTANT CHANGE, UPGRADE AT ONCE ***
fixed insecure temporary file creation
*****************************************
@@ -10,6 +10,8 @@ version 0.9 -- unreleased
rdiff handler now supports remote source and local dest.
(patch from cmccallum@thecsl.org).
man pages are greatly improved.
+ fixed many bugs in rdiff helper.
+ rdiff handler does not require 'label'
version 0.8 -- September 15 2005
added pgsql (PostgreSQL) handler, with vservers support.
diff --git a/handlers/easydialog.sh b/handlers/easydialog.sh
index 5d70653..18cb7c3 100644
--- a/handlers/easydialog.sh
+++ b/handlers/easydialog.sh
@@ -237,7 +237,12 @@ formDisplay() {
done
) | xargs $DIALOG 2> $temp
local status=$?
- [ $status = 0 ] && REPLY=`cat $temp`
+
+ if [ $status = 0 ]; then
+ IFS=$''
+ REPLY=`cat $temp`
+ IFS=$' \t\n'
+ fi
rm -f $temp
return $status
}
diff --git a/handlers/rdiff b/handlers/rdiff
index 40ad52d..9de8650 100644
--- a/handlers/rdiff
+++ b/handlers/rdiff
@@ -3,20 +3,83 @@
# requires rdiff-backup
#
+### FUNCTIONS ###
+
+function test_connection() {
+ # given a user and host,
+ # tests the connection.
+ # if user or host is missing, returns 0
+ # (ie, assume it's a local connection).
+ if [ $# -lt 2 ]; then
+ debug "(local is assumed to be a good connection)"
+ return 0
+ fi
+ local user=$1
+ local host=$2
+ debug "ssh -o PasswordAuthentication=no $host -l $user 'echo -n 1'"
+ local ret=`ssh -o PasswordAuthentication=no $host -l $user 'echo -n host is alive'`
+ if echo $ret | grep "host is alive"; then
+ debug "Connected to $host as $user successfully"
+ else
+ fatal "Can't connect to $host as $user."
+ fi
+}
+
+function get_version() {
+ # given no arguments, returns the local version.
+ # given a user and host, returns the remote version.
+ # if user or host is missing, returns the local version.
+ if [ "$#" -lt 2 ]; then
+ debug "$RDIFFBACKUP -V"
+ echo `$RDIFFBACKUP -V`
+ else
+ local user=$1
+ local host=$2
+ debug "ssh $host -l $user '$RDIFFBACKUP -V'"
+ echo `ssh $host -l $user "$RDIFFBACKUP -V | grep rdiff-backup"`
+ fi
+}
+
+function check_consistency() {
+ local section=$1
+ local type=$2
+ local user=$3
+ local host=$4
+ if [ "$type" == "local" ]; then
+ if [ "$user" != "" ]; then
+ warning "User should not be specified for local $section."
+ fi
+ if [ "$host" != "" ]; then
+ warning "Host should not be specified for local $section."
+ fi
+ fi
+ if [ "$type" == "remote" ]; then
+ if [ "$user" == "" ]; then
+ fatal "User must be specified for remote $section."
+ fi
+ if [ "host" == "" ]; then
+ fatal "Host must be specifed for remote $section."
+ fi
+ fi
+}
+
+### GET CONFIG ###
+
getconf options
getconf testconnect yes
getconf nicelevel 0
setsection source
getconf type; sourcetype=$type
+getconf user; sourceuser=$user
+getconf host; sourcehost=$host
+check_consistency "source" "$type" "$user" "$host"
getconf label
getconf keep 60
getconf include
getconf vsinclude
getconf exclude
-### DESTINATION ###
-
setsection dest
getconf directory; destdir=$directory
# strip trailing /
@@ -24,6 +87,9 @@ destdir=${destdir%/}
getconf type; desttype=$type
getconf user; destuser=$user
getconf host; desthost=$host
+check_consistency "destination" "$type" "$user" "$host"
+
+### CHECK CONFIG ###
# See if vservers are configured
if [ "$vservers" = "yes" ]
@@ -37,47 +103,44 @@ then
fi
fi
-[ "$destdir" != "" ] || fatal "Destination directory not set"
-
-if [ "$desttype" == "remote" ]; then
- # see if we can login
- if [ "$testconnect" == "yes" ]; then
- hostalive=0
- debug "ssh -o PreferredAuthentications=publickey $desthost -l $destuser 'echo -n 1'"
- ret=`ssh -o PreferredAuthentications=publickey $desthost -l $destuser 'echo -n host is alive'`
- if echo $ret | grep "host is alive"; then
- debug "Connected to $desthost as $destuser successfully"
- else
- fatal "Can't connect to $desthost as $destuser."
- fi
- fi
- # see that rdiff-backup has the same version as here
- debug "ssh -o PreferredAuthentications=publickey $desthost -l $destuser '$RDIFFBACKUP -V'\""
- remoteversion=`ssh -o PreferredAuthentications=publickey $desthost -l $destuser "$RDIFFBACKUP -V | grep rdiff-backup"`
- localversion=`$RDIFFBACKUP -V`
- if [ "$remoteversion" != "$localversion" ]; then
- fatal "rdiff-backup does not have the same version on this computer and the backup server."
- fi
- execstr_serverpart="$destuser@$desthost::$destdir/$label"
-else
- execstr_serverpart="$destdir/$label"
+# check the connection at the source and destination
+if [ "$testconnect" == "yes" -o $test ]; then
+ test_connection $sourceuser $sourcehost
+ test_connection $destuser $desthost
fi
-### SOURCE ###
+# see that rdiff-backup has the same version at the source and destination
+sourceversion=`get_version $sourceuser $sourcehost`
+destversion=`get_version $destuser $desthost`
+if [ "$sourceversion" != "$destversion" ]; then
+ fatal "rdiff-backup does not have the same version at the source and at the destination."
+fi
-[ "$sourcetype" == "local" ] || fatal "Only local source type supported"
+# source specific checks
[ "$include" != "" -o "$vsinclude" != "" ] || fatal "No source includes specified"
#TODO should I test for vsinclude if usevservers=1?
+case $sourcetype in
+ remote ) execstr_sourcepart="$sourceuser@$sourcehost::/" ;;
+ local ) execstr_sourcepart="/" ;;
+ * ) fatal "sourcetype '$sourcetype' is neither local nor remote" ;;
+esac
-execstr_clientpart="/"
+# destination specific checks
+[ "$destdir" != "" ] || fatal "Destination directory not set"
+case $desttype in
+ remote ) execstr_destpart="$destuser@$desthost::$destdir/$label" ;;
+ local ) execstr_destpart="$destdir/$label" ;;
+ * ) fatal "desttype '$desttype' is neither local nor remote" ;;
+esac
-## REMOVE OLD BACKUPS
+### REMOVE OLD BACKUPS ###
if [ "`echo $keep | tr -d 0-9`" == "" ]; then
+ # add D if no other date unit is specified
keep="${keep}D"
fi
-removestr="rdiff-backup --force --remove-older-than $keep "
+removestr="$RDIFFBACKUP --force --remove-older-than $keep "
if [ "$desttype" == "remote" ]; then
removestr="${removestr}${destuser}@${desthost}::"
fi
@@ -86,8 +149,7 @@ removestr="${removestr}${destdir}/${label}";
debug "$removestr"
if [ ! $test ]; then
output=`$removestr 2>&1`
- code=$?
- if [ "$code" == "0" ]; then
+ if [ $? = 0 ]; then
debug $output
info "Removing backups older than $keep days succeeded."
else
@@ -96,31 +158,27 @@ if [ ! $test ]; then
fi
fi
-## EXECUTE ##
+### EXECUTE ###
execstr="$RDIFFBACKUP $options --print-statistics "
# TODO: order the includes and excludes
-
# excludes
for i in $exclude; do
str="${i//__star__/*}"
execstr="${execstr}--exclude '$str' "
done
-
# includes
for i in $include; do
+ [ "$i" != "/" ] || fatal "Sorry, you cannot use 'include = /'"
str="${i//__star__/*}"
execstr="${execstr}--include '$str' "
done
# vsinclude
-if [ $usevserver ]
-then
- for vserver in `ls $VROOTDIR | grep -E -v "lost+found|ARCHIVES"`
- do
- for vi in $vsinclude
- do
+if [ $usevserver ]; then
+ for vserver in `ls $VROOTDIR|grep -v lost+found`; do
+ for vi in $vsinclude; do
str="${vi//__star__/*}"
execstr="${execstr}--include '$VROOTDIR/$vserver$str' "
done
@@ -131,13 +189,12 @@ fi
execstr="${execstr}--exclude '/*' "
# include client-part and server-part
-execstr="${execstr}$execstr_clientpart $execstr_serverpart"
+execstr="${execstr}$execstr_sourcepart $execstr_destpart"
debug "$execstr"
if [ ! $test ]; then
output=`nice -n $nicelevel su -c "$execstr" 2>&1`
- code=$?
- if [ "$code" == "0" ]; then
+ if [ $? = 0 ]; then
debug $output
info "Successfully finished backing up source $label"
else
diff --git a/handlers/rdiff.helper b/handlers/rdiff.helper
index 8be68ac..066d53a 100644
--- a/handlers/rdiff.helper
+++ b/handlers/rdiff.helper
@@ -1,68 +1,78 @@
HELPERS="$HELPERS rdiff:incremental_remote_filesystem_backup"
+declare -a rdiff_includes
+declare -a rdiff_excludes
+
do_rdiff_dest() {
- formBegin "rdiff action wizard"
- formItem "keep" "$rdiff_keep"
- formItem "dest_directory" "$rdiff_directory"
- formItem "dest_host" "$rdiff_host"
- formItem "dest_user" "$rdiff_user"
- formDisplay
- [ $? = 1 ] && return;
-
- set -- $REPLY
- rdiff_keep=$1
- rdiff_directory=$2
- rdiff_host=$3
- rdiff_user=$4
+ set -o noglob
+ formBegin "rdiff action wizard"
+ formItem "keep" "$rdiff_keep"
+ formItem "dest_directory" "$rdiff_directory"
+ formItem "dest_host" "$rdiff_host"
+ formItem "dest_user" "$rdiff_user"
+ formDisplay
+ [ $? = 1 ] && return;
+
+ IFS=$''
+ replyconverted=`echo $REPLY | tr '\n' :`
+ IFS=$':'
+ thereply=($replyconverted)
+ IFS=$' \t\n'
+
+ rdiff_keep=${thereply[0]}
+ rdiff_directory=${thereply[1]}
+ rdiff_host=${thereply[2]}
+ rdiff_user=${thereply[3]}
_dest_done="(DONE)"
setDefault conn
+ set +o noglob
}
do_rdiff_src() {
- formBegin "rdiff action wizard: includes"
- formItem include /var/spool/cron/crontabs
- formItem include /var/backups
- formItem include /etc
- formItem include /root
- formItem include /home
- formItem include '/usr/local/*bin'
- formItem include '/var/lib/dpkg/status*'
- formItem include
- formItem include
- formItem include
- formDisplay
- [ $? = 1 ] && return;
-
- rdiff_includes=
- set -o noglob
- for i in $REPLY; do
- [ "$i" != "" ] && rdiff_includes="$rdiff_includes\ninclude = $i"
- done
- set +o noglob
-
- formBegin "rdiff action wizard: excludes"
- formItem exclude '/home/*/.gnupg'
- formItem exclude
- formItem exclude
- formDisplay
- [ $? = 1 ] && return;
-
- rdiff_excludes=
- set -o noglob
- for i in $REPLY; do
- [ "$i" != "" ] && rdiff_excludes="$rdiff_excludes\nexclude = $i"
- done
- set +o noglob
+ #echo ${rdiff_includes[@]}
+ set -o noglob
+ formBegin "rdiff action wizard: includes"
+ for ((i=0; i < ${#rdiff_includes[@]} ; i++)); do
+ formItem include ${rdiff_includes[$i]}
+ done
+ formItem include
+ formItem include
+ formItem include
+ formDisplay
+ [ $? = 1 ] && return;
+
+ unset rdiff_includes
+ rdiff_includes=($REPLY)
+
+ formBegin "rdiff action wizard: excludes"
+ for ((i=0; i < ${#rdiff_excludes[@]} ; i++)); do
+ formItem exclude ${rdiff_excludes[$i]}
+ done
+ formItem exclude
+ formItem exclude
+ formDisplay
+ [ $? = 1 ] && return;
+
+ unset rdiff_excludes
+ rdiff_excludes=($REPLY)
- _src_done="(DONE)"
- setDefault dest
+ _src_done="(DONE)"
+ setDefault dest
+ set +o noglob
}
do_rdiff_con() {
+ IFS=$' \t\n'
if [ "$_dest_done" = "" ]; then
- msgBox "rdiff action wizard: error" "You must first configure the destination"
+ msgBox "rdiff action wizard: error" "You must first configure the destination."
+ return
+ elif [ "$rdiff_user" = "" ]; then
+ msgBox "rdiff action wizard: error" "You must first configure the destination user."
+ return
+ elif [ "$rdiff_host" = "" ]; then
+ msgBox "rdiff action wizard: error" "You must first configure the destination host."
return
else
booleanBox "rdiff action wizard" "This step will create a ssh key for the local root user with no passphrase (if one does not already exist), and attempt to copy root's public ssh key to authorized_keys file of $rdiff_user@$rdiff_host. This will allow the local root to make unattended backups to $rdiff_user@$rdiff_host. Are you sure you want to continue?"
@@ -78,15 +88,18 @@ do_rdiff_con() {
ssh -o PreferredAuthentications=publickey $rdiff_host -l $rdiff_user "exit" 2> /dev/null
if [ $? -ne 0 ]; then
- echo "Copying root's public ssh key to authorized_keys of $rdiff_user@$rdiff_host. Specify the password for user $rdiff_user@$rdiff_host."
+ echo "Copying root's public ssh key to authorized_keys of $rdiff_user@$rdiff_host. When prompted, specify the password for user $rdiff_user@$rdiff_host."
ssh-copy-id -i /root/.ssh/id_[rd]sa.pub $rdiff_user@$rdiff_host
if [ $? -ne 0 ]; then
- echo "Couldn't copy root's public ssh key to authorized_keys of $rdiff_user@$rdiff_host. This time, testing whether directory is writable."
+ echo "FAILED: Couldn't copy root's public ssh key to authorized_keys of $rdiff_user@$rdiff_host."
ssh $rdiff_user@$rdiff_host 'test -w .ssh || test -w .'
- case $? in
+ result=$?
+ echo "Hit return to continue."
+ read
+ case $result in
0 ) msgBox "rdiff action wizard: error" "Directories are writable: Probably just a typo the first time." ;;
1 ) msgBox "rdiff action wizard: error" "Connected successfully to $rdiff_user@$rdiff_host, but unable to write. Check ownership and modes of ~$rdiff_user on $rdiff_host." ;;
- 255 ) msgBox "rdiff action wizard: error" "Failed to connect to $rdiff_user@$rdiff_host. Check hostname, username, and password." ;;
+ 255 ) msgBox "rdiff action wizard: error" "Failed to connect to $rdiff_user@$rdiff_host. Check hostname, username, and password. Also, make sure sshd is running on the destination host." ;;
* ) msgBox "rdiff action wizard: error" "Unexpected error." ;;
esac
return
@@ -112,9 +125,15 @@ do_rdiff_finish() {
type = local
keep = $rdiff_keep
EOF
- echo -n -e "$rdiff_includes" >> $next_filename
- echo -e "$rdiff_excludes" >> $next_filename
- cat >> $next_filename <<EOF
+ set -o noglob
+ for ((i=0; i < ${#rdiff_includes[@]} ; i++)); do
+ echo include = ${rdiff_includes[$i]}
+ done
+ for ((i=0; i < ${#rdiff_includes[@]} ; i++)); do
+ echo exclude = ${rdiff_excludes[$i]}
+ done
+ set +o noglob
+ cat >> $next_filename <<EOF
[dest]
type = remote
@@ -126,6 +145,7 @@ EOF
}
rdiff_main_menu() {
+
while true; do
srcitem="choose files to include & exclude $_src_done"
destitem="configure backup destination $_dest_done"
@@ -138,6 +158,7 @@ rdiff_main_menu() {
finish "finish and create config file"
[ $? = 1 ] && return;
result="$REPLY"
+
case "$result" in
"src") do_rdiff_src;;
"dest") do_rdiff_dest;;
@@ -152,12 +173,12 @@ rdiff_main_menu() {
fi
;;
esac
-
+
done
}
rdiff_wizard() {
-# require_packages rdiff-backup
+ require_packages rdiff-backup
_src_done=
_dest_done=
_con_done=
@@ -166,6 +187,8 @@ rdiff_wizard() {
rdiff_directory=/backup/`hostname`
rdiff_user=
rdiff_host=
+ rdiff_includes=(/var/spool/cron/crontabs /var/backups /etc /root /home /usr/local/*bin /var/lib/dpkg/status*)
+ rdiff_excludes=(/home/*/.gnupg)
rdiff_main_menu
}
diff --git a/ninjahelper b/ninjahelper
index 817b47b..13a4ca9 100755
--- a/ninjahelper
+++ b/ninjahelper
@@ -144,7 +144,7 @@ doaction() {
$enable "$enable action" \
name "change the filename" \
run "run this action now" \
- test "do a test run" \
+ test "test connections and passwords only" \
kill "remove this action"
[ $? = 1 ] && return;
result="$REPLY"
@@ -237,7 +237,7 @@ for file in `find $conf/etc/backup.d/ -type f | sort -n`; do
let "i += 1"
done
-menuBox "main menu" "select an action to edit" $menulist \
+menuBox "main menu" "Select a backup action for more options, or create a new action:" $menulist \
new "create a new backup action" \
quit "leave ninjahelper"