[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Bash commands

Russell <rjshaw@iprimus.com.au> [2002-09-02 11:42:45 +1000]:
> Thanks for the tips. I'm getting better;)
> I've been making this backup script which
> is nearly complete:

I am going to leave the full quoted script so that I can comment on
the parts I want to comment upon.  (Normally I would trim more.)

> #!/bin/sh
> #
> # Russ' backup
> #
> # Warning: Do not run unless you understand every line of this script
> #
> # Copy everything (almost) from the system to a backup removeable hard-disk
> # Assumptions:
> #  run in super-user mode
> #  the spare hard-disk has enough capacity
> #  the spare disk has been formatted to match the original
> #    in number and type of partitions
> #
> # The spare disk won't be bootable unless lilo is run separately,
> #  which i haven't got around to doing yet
> # The /boot partition:
> HDD_BOOT=hdc1
> # The main root / partition:
> HDD_MAIN=hdc3
> # Mount /boot partition
> if ! mount | grep -qs /dev/$HDD_BOOT
> then
>   if ! mount -t ext2 /dev/$HDD_BOOT /mnt
>   then
>     echo "Removeable /dev/$HDD_BOOT not working"
>     exit 1
>   fi
> fi
> # Copy /boot partition
> echo "Updating /boot"
> if ! cp -auv /boot /mnt
> then
>   echo "Failed to update /boot"
>   exit 1
> fi

You might consider using 'rsync' here.  Especially since this is a
backup you will be doing the backup when probably nothing has changed.
But the 'cp' will always copy all of the files regardless.  Putting an
rsync here instead will only copy what has changed.

Also, as a backup what happens when you remove a file from your
working directory?  Will the copy _ever_ be removed from backup?  This
depends upon what you want.  If you were writing to a new CD each time
it would not be a question.  But if you are keeping a backup on disk
somewhere then you probably want to delete it from disk eventually.
What I do is to have rsync rotate me older copies.  I will include an
example at the bottom.

> # Mount main partition
> umount /mnt
> if ! mount | grep -qs /dev/$HDD_MAIN
> then
>   if ! mount -t ext2 /dev/$HDD_MAIN /mnt
>   then
>     echo "Removeable $HDD_MAIN not working"
>     exit 1
>   fi
> fi
> # Copy everything on main partition
> # Strip some top level directories we don't want to copy
> FILES=$( ls / | sed -e s/boot//g | sed -e s/cdrom//g | sed -e s/proc//g | sed -e s/floppy//g | sed -e s/mnt//g | sed -e s/dev//g)
> # Note: I really want to copy some of these directories and their contents with
> #       any attributes preserved, but without copying the contents of the files
> #       (haven't figured out a command for that yet)

That sed is pretty clever.  But extremely unwieldy.  To do exactly
what you are doing easier I would use 'grep -v -e pat1 -e pat2'.  Try
that and add it to your toolbox of shell scripting.

But even better is to avoid that entirely.  I can think of two
different ways of doing that.  Perhaps you will like the grep way
better but just for the sake of discussion I am going to post another

> OPTS="-auv"
> for i in $FILES
> do
>   echo "Updating /$i"
>   if ! chroot / cp $OPTS $i /mnt

What does the chroot do for you here?  I don't think you want this.

>   then
>     echo "Failed to update /$i"
>     exit 1
>   fi
> done
> echo "System backup successful"
> exit 0

How about this?  I had to do some on the fly translations.  I
undoubtedly made some errors which you will have to debug.  Don't use
this with out approaching it as a task to debug.  But this is my
normal method to backup my system.  I usually go from one host to a
different backup host but the concept is the same.

# This is the destination of the backup.

# For rotating incrementals use the three letter day name.
BACKUPDIR=incr-$(date '+%Y-%m-%d')

OPTS="-a --delete --numeric-ids --backup --backup-dir=$DESTDIR/$BACKUPDIR"
for i in $FILES
  case "$i" in
  /boot) continue ;;
  /cdrom) continue ;;
  /proc) continue ;;
  /floppy) continue ;;
  /mnt) continue ;;
  /dev) continue ;;

  echo "Updating /$i"
  if ! rsync $OPTS $i $DESTDIR/$host/current/
    echo "Failed to update /$i"
    exit 1

This will produce something like this:
  current/          incr-2002-08-23/  incr-2002-08-27/  incr-2002-08-31/
  incr-2002-08-20/  incr-2002-08-24/  incr-2002-08-28/  incr-2002-09-01/
  incr-2002-08-21/  incr-2002-08-25/  incr-2002-08-29/  incr-2002-09-02/
  incr-2002-08-22/  incr-2002-08-26/  incr-2002-08-30/

Since I want to keep two weeks of rotating backup I delete anything
that is later than two weeks.  The dated names are forcing an order.
Therefore I remove the ones that fall off of the end.  Which means
that if the backup stop working for a few days that I still keep 14
incrementals and never delete unless I have 14 incrementals after it.

list=$(ls -1dr $DESTDIR/incr-* | sed -e 1,14d)
if [ -n "$list" ]; then
  rm -rf $(ls -1dr $DESTDIR/incr-* | sed -e 1,14d)

Remember that I did some on the fly translations of my script and
almost certainly introduced a bug in this posting of it.  Any time you
do something as root with a script that can copy or delete you need to
be careful to treat it suspect and debug it carefully.

Look at http://rsync.samba.org for more information on rsync.
Especially their FAQ section and examples section is good for recipies
such as this.


Attachment: pgppC30SPq6MD.pgp
Description: PGP signature

Reply to: