11. 스크립트들(The Scripts)

스크립트가 무엇을 하는가에 대한 설명은 스크립트의 시작 부분의 주의 사항을 보라.

11.1. 1단계(First Stage)

11.1.1. make.fdisk

백업시 실행되는 이 스크립트는 복구시에도 실행되어 아래의 make.dev.hda와 비슷한 스크립트를 만들어 낸다. 이것은 아래의 dev.hda와 유사한 자료 파일도 만들어 낸다. 스크립트의 이름과 만들어지는 자료 파일의 이름은 이 스크립트에 매개변수로 주어지는 장치에 따라 달라진다. 복구시에 실행되는 그 스크립트는 하드드라이브에 분할영역을 새로이 만들어 낸다. make.fdisk는 아래의 save.metadata로부터 이름이 유래했다.

#! /usr/bin/perl

# A perl script to create a script and input file for fdisk to
# re-create the partitions on the hard disk, and format the Linux and
# Linux swap partitions. The first parameter is the fully qualified
# path of the device of the hard disk, e.g. /dev/hda. The two
# resulting files are the script make.dev.x and the data file dev.x
# (where x is the hard drive described, e.g. hda, sdc). make.dev.x is
# run at restore time to rebuild hard drive x, prior to running
# restore.metadata. dev.x is the input file for fdisk.

# Time-stamp: <2002-09-10 10:18:44 root make.fdisk>

# Copyright 2001 through the last date of modification Charles Curley
# except for the subroutine cut2fmt.

# cut2fmt Copyright (c) 1998 Tom Christiansen, Nathan Torkington and
# O'Reilly & Associates, Inc.  Permission is granted to use this code
# freely EXCEPT for book publication.  You may use this code for book
# publication only with the explicit permission of O'Reilly &
# Associates, Inc.

# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.

# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.

# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

# In addition, as a special exception, Tom Christiansen, Nathan
# Torkington and O'Reilly & Associates, Inc.  give permission to use
# the code of this program with the subroutine cut2fmt (or with
# modified versions of the subroutine cut2fmt that use the same
# license as the subroutine cut2fmt), and distribute linked
# combinations including the two.  You must obey the GNU General
# Public License in all respects for all of the code used other than
# the subroutine cut2fmt.  If you modify this file, you may extend
# this exception to your version of the file, but you are not
# obligated to do so.  If you do not wish to do so, delete this
# exception statement and the subroutine cut2fmt from your version.

# You can also contact the Free Software Foundation at http://www.fsf.org/

# Changes:

# 2002 09 08: Added minimal support for ext3fs. We now detect mounted
# ext3fs partitions & rebuild but with no options. The detection
# depends on the command line "dumpe2fs <device> 2>/dev/null | grep -i
# journal" producing no output for an ext2fs, and output (we don't
# care what) for an ext3fs.

# This could stand extension to support non-default ext3 options such
# as the type of journaling. Volunteers?

# 2002 07 25: Bad block checking is now a command line option (-c) at
# the time the product script is run.

# 2002 07 03: Corrected the mechanism for specifying the default
# drive.

# 2001 11 25: Changed the way mke2fs gets its bad block
# list. badblocks does not guess at the block size, so you have to get
# it (from dumpe2fs) and feed it to badblocks. It is simpler to just
# have mke2fs call badblocks, but you do loose the ability to have a
# writing test easily. -- C^2

# 2001 11 25: Changed the regex that extracts partition labels from
# the mount command. This change does not affect the results at all,
# it just makes it possible to use Emacs' perl mode to indent
# correctly. I just escaped the left bracket in the regex. -- C^2

# Discussion:

# fdisk will spit out a file of the form below if you run it as "fdisk
# -l".

# root@tester ~/bin $ fdisk -l /dev/hda

# Disk /dev/hda: 64 heads, 63 sectors, 1023 cylinders
# Units = cylinders of 4032 * 512 bytes

#    Device Boot    Start       End    Blocks   Id  System
# /dev/hda1             1         9     18112+  83  Linux
# /dev/hda2            10      1023   2044224    5  Extended
# /dev/hda5            10       368    723712+  83  Linux
# /dev/hda6           369       727    723712+  83  Linux
# /dev/hda7           728       858    264064+  83  Linux
# /dev/hda8           859       989    264064+  83  Linux
# /dev/hda9           990      1022     66496+  82  Linux swap

# What fdisk does not do is provide output suitable for later
# importing into fdisk, a la sfdisk. This script parses the output
# from fdisk and creates an input file for fdisk. Use the input file
# like so:

# fdisk /dev/hdx < dev.hdx

# For the bare metal restore package, this script also builds a script
# that will execute the above command so you can run it from your zip
# disk. Because the bare metal restore scripts all are in /root/bin,
# the data file and script created by this script are also placed
# there. The same script also creates appropriate Linux file systems,
# either ext2fs, or Linux swap. There is limited support for FAT12 and
# FAT16. There is no support right now (hint, hint) for FAT32. For
# anything else, you're on your own.

# Note for FAT32: According to the MS KB, there are more than one
# reserved sectors for FAT32, usually 32, but it can vary. Do a search
# in M$'s KB for "boot sector" or BPB for the gory details. For more
# info than you really need on how boot sectors are used, see
# http://support.microsoft.com/support/kb/articles/Q140/4/18.asp

# You can also edit dev.x to change the sizes of partitions. Don't
# forget, if you change the size of a FAT partition across the 32MB
# boundary, you need to change the type as well! Run "fdisk /dev/hda"
# or some such, then the l command to see the available partition
# types. Then go ahead and edit dev.x appropriately. Also, when moving
# partition boundarys with hand edits, make sure you move both logical
# and extended partition boundaries appropriately.

# Bad block checking right now is a quick read of the partition. A
# writing check is also possible but more difficult. You have to run
# badblocks as a separate command, and pass the bad block list to
# mke2fs in a file (in /tmp, which is a ram disk). You also have to
# know how large the blocks are, which you learn by running
# dumpe2fs. It gets messy and I haven't done it yet. You probably
# don't need it for a new hard drive, but if you have had a hard drive
# crash on you and you are reusing it (while you are waiting for its
# replacement to come in, I presume), then I highly recommend it. Let
# me know how you do it.

# For more information contact the author, Charles Curley, at
# http://w3.trib.com/~ccurley/.


# cut2fmt figures out the format string for the unpack function we use
# to slice and dice the output from fdisk. From Christiansen and
# Torkington, Perl Cookbook 5.

sub cut2fmt {
    my (@positions) = @_;
    my $template    = '';
    my $lastpos     = 1;

    foreach $place (@positions) {
	$template .= "A" . ($place - $lastpos) . " ";
	$lastpos = $place;
    }

    $template .= "A*";
    return $template;
}


# Begin main line code.



# Provide a default device.

# print "\$ARGV[0] is $ARGV[0].\n";

$device = defined ($ARGV[0]) ? $ARGV[0] : "/dev/hda";

# print "Device is $device.\n";

# prepare format string.
$fmt = cut2fmt (11, 19, 24, 34, 45, 49);
# print "Format string is $fmt.\n\n";

# define fields in the array @_.
$dev = 0;
$bootable = 1;
$firstcyl = 2;
$lastcyl = 3;
$parttype = 5;
$partstring = 6;

$target = "\/target";

$outputfilename = $device;
$outputfilename =~ s/\//./g;
$outputfilename = substr ($outputfilename, 1, 100);

$outputfilepath = "\/root\/bin\/";


# Make a hash of the labels.
$mpid = open (MOUNT, "mount -l |") or die "Couldn't fork: $!\n";
while (<MOUNT>) {
    if ($_ =~ /^$device/i) {	# is this a line with a partition in it?
#     	print $_;		# print it just for grins
	split;
	if ($_[6] ne "") {	# only process if there actually is a label
	    $_[6] =~ s/[\[\]]//g; # strike [ and ].
	    $labels{$_[0]} = $_[6];
#	    print "The label of file device $_[0] is $labels{$_[0]}.\n";
	}


	# We only mount if it's ext2fs or ext3fs and read and write.

	if ($_[4] =~ /ext[23]/ and $_[5] eq "(rw)" ) {
            $mountpoints{$_[2]} = $_[0];
#           print "$_[2] is the mountpoint for $mountpoints{$_[2]}.\n";
	}
    }
}
close (MOUNT);


$fpid = open (FDISK, "fdisk -l $device |") or die "Couldn't fork: $!\n";

open (OUTPUT, "> $outputfilepath${outputfilename}")
    or die "Couldn't open output file $outputfilepath${outputfilename}.\n";

while (<FDISK>) {
    if ($_ =~ /^$device/i) {	# is this a line with a partition in it?
#   	print $_;		# print it just for grins
	chop;			# kill trailing \r
	@_ = unpack ($fmt, $_);

	# now strip white spaces from cylinder numbers
	@_[$firstcyl] =~ s/[ \t]+//;
	@_[$lastcyl] =~ s/[ \t]+//;
	@_[$parttype] =~ s/[ \t]+//;

	$partnumber = substr(@_[$dev], 8, 10); # get partition number for this line
	# just for grins
#  	print "  $partnumber, @_[$firstcyl], @_[$lastcyl], @_[$partstring]\n";

	# Here we start creating the input to recreate the partition
	# this line represents.

	print OUTPUT "n\n";
	if ($partnumber < 5) {
	    # primary Linux partition
	    if (@_[$parttype] == 83) {
		print OUTPUT "p\n$partnumber\n@_[$firstcyl]\n";
		if (@_[$firstcyl] ne @_[$lastcyl]) { # in case it's all on one cylinder
		    print OUTPUT "@_[$lastcyl]\n";
		}

		# Now detect if this is an ext3 (journaling)
		# partition. We do this using dumpe2fs to dump the
		# partition and grepping on "journal". If the
		# partition is ext2, there will be no output. If it is
		# ext3, there will be output, and we use that fact to
		# set a command line switch. The command line switch
		# goes into an associative array (hash) so we don't
		# have to remember to reset it to the null string when
		# we're done.

		$dpid = open (DUMPE2FS, "dumpe2fs @_[$dev] 2>/dev/null | grep -i journal |")
		    or die "Couldn't fork: $!\n";
		while (<DUMPE2FS>) {
# 		    print "Dumpe2fs: $_";
		    $ext3{$_[$dev]} = "-j ";
		    last;
		}
		close (DUMPE2FS);

		if ($labels{@_[$dev]}) { # do we have a label?
		    $format .= "echo\necho formatting $checking@_[$dev]\n";
		    $format .= "mke2fs $ext3{$_[$dev]}\$blockcheck -L $labels{@_[$dev]} @_[$dev]\n\n";
		} else {
		    $format .= "echo\necho formatting $checking@_[$dev]\n";
		    $format .= "mke2fs $ext3{$_[$dev]}\$blockcheck @_[$dev]\n\n";
		}

		# extended partition
	    } elsif (@_[$parttype] == 5) {
		print OUTPUT "e\n$partnumber\n@_[$firstcyl]\n";
		if (@_[$firstcyl] ne @_[$lastcyl]) {
		    print OUTPUT "@_[$lastcyl]\n";
		}

		# primary Linux swap partition
	    } elsif (@_[$parttype] == 82) {
		print OUTPUT "p\n$partnumber\n@_[$firstcyl]\n";
		if (@_[$firstcyl] ne @_[$lastcyl]) {
		    print OUTPUT "@_[$lastcyl]\n";
		}
		print OUTPUT "t\n$partnumber\n82\n";
		$format .= "echo Making @_[$dev] a swap partition.\n";
		$format .= "mkswap \$blockcheck @_[$dev]\n\n";

		# primary mess-dos partition. We don't handle FAT32,
		# which requires a command line switch for mkdosfs.
	    } elsif ( @_[$parttype] == 1 || @_[$parttype] == 4 || @_[$parttype] == 6 ) {
		print ("dd if=@_[$dev] of=$outputfilepath$outputfilename$partnumber");
		print (" bs=512 count=1\n");
		system ("dd if=@_[$dev] of=$outputfilepath$outputfilename$partnumber bs=512 count=1");
		print OUTPUT "p\n$partnumber\n@_[$firstcyl]\n";
		if (@_[$firstcyl] ne @_[$lastcyl]) { # in case it's all on one cylinder
		    print OUTPUT "@_[$lastcyl]\n";
		}
		print OUTPUT "t\n$partnumber\n@_[$parttype]\n";
		$format .= "echo\necho formatting $checking@_[$dev]\n";
		$format .= "mkdosfs \$blockcheck @_[$dev]\n";
		$format .= "# restore FAT boot sector.\n";
		$format .= "dd if=$outputfilename$partnumber of=@_[$dev] bs=512 count=1\n\n";

	    } else {
		# anything else partition
		print OUTPUT "p\n@_[$firstcyl]\n";
		if (@_[$firstcyl] ne @_[$lastcyl]) {
		    print OUTPUT "@_[$lastcyl]\n";
		}
		print OUTPUT "t\n$partnumber\n@_[$parttype]\n";
	    }

	} else {
	    # logical Linux partition
	    if (@_[$parttype] == 83) {
		print OUTPUT "l\n@_[$firstcyl]\n";
		if (@_[$firstcyl] ne @_[$lastcyl]) {
		    print OUTPUT "@_[$lastcyl]\n";
		}

		# Now detect if this is an ext3 (journaling)
		# partition. We do this using dumpe2fs to dump the
		# partition and grepping on "journal". If the
		# partition is ext2, there will be no output. If it is
		# ext3, there will be output, and we use that fact to
		# set a command line switch. The command line switch
		# goes into an associative array (hash) so we don't
		# have to remember to reset it to the null string when
		# we're done.

		$dpid = open (DUMPE2FS, "dumpe2fs @_[$dev] 2>/dev/null | grep -i journal |")
		    or die "Couldn't fork: $!\n";
		while (<DUMPE2FS>) {
# 		    print "Dumpe2fs: $_";
		    $ext3{$_[$dev]} = "-j ";
		    last;
		}
		close (DUMPE2FS);

		if ($labels{@_[$dev]}) { # do we have a label?
		    $format .= "echo\necho formatting $checking@_[$dev]\n";
		    $format .= "mke2fs $ext3{@_[$dev]}\$blockcheck -L $labels{@_[$dev]} @_[$dev]\n\n";
		} else {
		    $format .= "echo\necho formatting $checking@_[$dev]\n";
		    $format .= "mke2fs $ext3{@_[$dev]}\$blockcheck @_[$dev]\n\n";
		}

		# logical Linux swap partition
	    } elsif (@_[$parttype] == 82 ) {
		print OUTPUT "l\n@_[$firstcyl]\n";
		if (@_[$firstcyl] ne @_[$lastcyl]) {
		    print OUTPUT "@_[$lastcyl]\n";
		}
		print OUTPUT "t\n$partnumber\n82\n";
		$format .= "echo Making @_[$dev] a swap partition.\n";
		$format .= "mkswap \$blockcheck @_[$dev]\n\n";

		# primary mess-dos partition. We don't handle FAT32,
		# which requires a command line switch for mkdosfs.
	    } elsif ( @_[$parttype] == 1 || @_[$parttype] == 4 || @_[$parttype] == 6 ) {
		print ("dd if=@_[$dev] of=$outputfilepath$outputfilename$partnumber");
		print (" bs=512 count=1\n");
		system ("dd if=@_[$dev] of=$outputfilepath$outputfilename$partnumber bs=512 count=1");
		print OUTPUT "p\n$partnumber\n@_[$firstcyl]\n";
		if (@_[$firstcyl] ne @_[$lastcyl]) { # in case it's all on one cylinder
		    print OUTPUT "@_[$lastcyl]\n";
		}
		print OUTPUT "t\n$partnumber\n@_[$parttype]\n";
		$format .= "echo\necho formatting $checking@_[$dev]\n";
		$format .= "mkdosfs \$blockcheck @_[$dev]\n";
		$format .= "# restore FAT boot sector.\n";
		$format .= "dd if=$outputfilename$partnumber of=@_[$dev] bs=512 count=1\n\n";

	    } else {
		# anything else partition
		print OUTPUT "l\n@_[$firstcyl]\n";
		if (@_[$firstcyl] ne @_[$lastcyl]) {
		    print OUTPUT "@_[$lastcyl]\n";
		}
		print OUTPUT "t\n$partnumber\n@_[$parttype]\n";
	    }

	}

	# handle bootable partitions
	if (@_[$bootable] =~ /\*/) {
	    print OUTPUT "a\n$partnumber\n";
	}
    }
}

print OUTPUT "v\nw\n";

close (OUTPUT);
close (FDISK);


open (OUTPUT, "> ${outputfilepath}make.$outputfilename")
    or die "Couldn't open output file ${outputfilepath}make.$outputfilename.\n";

print OUTPUT <<FINIS;
#! /bin/sh

# A script to restore the partition data of a hard drive and format
# the partitions. Created at bare metal backup time by the Perl script
# make.fdisk.

# Copyright 2001 through the last date of modification Charles Curley.

# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.

# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.

# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

# You can also contact the Free Software Foundation at http://www.fsf.org/

# For more information contact the author, Charles Curley, at
# http://w3.trib.com/~ccurley/.

export blockcheck=\$1;

if [ "\$blockcheck" != "-c" ] && [ -n "\$blockcheck" ]
then
    echo "\${0}: automated restore with no human interaction."
    echo "\${0}: -c: block check during file system making."
    exit 1;
fi

FINIS

# Clean the old partition table out.
print OUTPUT "dd if=/dev/zero of=$device bs=512 count=2\n\nsync\n\n";

print OUTPUT "fdisk $device \< $outputfilename\n\nsync\n\n";
print OUTPUT $format;

# Now build the mount points on the root and other partitions.

# We have a hash of mount points and devices in %mountpoints. However,
# we have to process them such that directories are built on the
# appropriate target partition. E.g. where /usr/local is on its own
# partition, we have to mount /usr before we build /usr/local. We can
# ensure this by sorting them. Shorter mount point paths will be built
# first. We can't sort a hash directly, so we use an array.

# We build commands to create the appropriate mount points and then
# mount the partitions to the mount points. This is in preparation for
# untarring the contents of the ZIP disk, done in restore.metadata.

foreach $point ( sort keys %mountpoints) {
    print OUTPUT "\n# $point is the mountpoint for $mountpoints{$point}.\n";
    print OUTPUT "mkdir $target$point\n";
    print OUTPUT "mount $mountpoints{$point} $target$point\n";
}


close (OUTPUT);

# These scripts are dangerous & should only be visible to root.

chmod 0700, "${outputfilepath}make.$outputfilename";
chmod 0600, "${outputfilepath}$outputfilename";

11.1.2. make.dev.hda

이 스크립트는 위의 make.fdisk에 의해서 만들어지는 파일 중 하나의 예이다. 자료 파일을 dev.hda와 같이 사용하며, 분할영역을 만들고 파일시스템을 만든다. 복구시에 가장 처음으로 실행되는 스크립트이다.

만약 여러분이 예를 들어 새 분할 영역을 추가하기 위해서 dev.hda를 편집할 만큼 용기가 있어 시도한다면, 이 스크립트 또한 편집해야 한다.

만약 여러분이 분할 영역에 대해 파일 시스템을 쓰려할 때 손상된 블록에 대하여 점검하기를 원한다면, "-c" 명령 옵션을 사용하라.

#! /bin/sh

# A script to restore the partition data of a hard drive and format
# the partitions. Created at bare metal backup time by the Perl script
# make.fdisk.

# Copyright 2001 through the last date of modification Charles Curley.

# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.

# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.

# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

# You can also contact the Free Software Foundation at http://www.fsf.org/

# For more information contact the author, Charles Curley, at
# http://w3.trib.com/~ccurley/.

dd if=/dev/zero of=/dev/hda bs=512 count=2

sync

fdisk /dev/hda < dev.hda

sync

echo
echo formatting and checking /dev/hda1
mkdosfs -c /dev/hda1
# restore FAT boot sector.
dd if=dev.hda1 of=/dev/hda1 bs=512 count=1

echo
echo formatting and checking /dev/hda2
badblocks -c 128 -o /tmp/dev.hda2 /dev/hda2
mke2fs -L /boot -l /tmp/dev.hda2 /dev/hda2

echo
echo formatting and checking /dev/hda5
badblocks -c 128 -o /tmp/dev.hda5 /dev/hda5
mke2fs -L / -l /tmp/dev.hda5 /dev/hda5

mkswap -c /dev/hda6



# / is the mountpoint for /dev/hda5.
mkdir /target/
mount /dev/hda5 /target/

# /boot is the mountpoint for /dev/hda2.
mkdir /target/boot
mount /dev/hda2 /target/boot

11.1.3. dev.hda

이 자료 파일은 복구시에 사용된다. make.dev.hda 스크립트에 의해 fdisk로 연결된다. 이 파일은 백업시에 make.fdisk 스크립트에 의해서 만들어진다. fdisk에 익숙한 사람들은 내용이 fdisk의 명령어나 사용되는 값(실린더 수 같은)이라는 것을 알 수 있을 것이다. 그러므로, 이 파일을 편집함으로써, 분할 영역의 크기를 바꾸고 새 분할영역을 더하는 것이 가능하다. 그래서 마지막에서 두 번째 명령어가 하드 드라이브에 쓰기 전에 분할 영역을 확인하는 것, v가 되는 것이다.

n
p
1
1
29
t
1
6
a
1
n
p
2
30
44
n
e
3
45
1023
n
l
45
944
n
l
945
1023
t
6
82
v
w

11.1.4. save.metadata

이 스크립트는 백업의 한 부분으로 실행되는 첫 스크립트이다. 이것은 위의 make.fdisk를 호출한다. 만약 여러분이 백업할 것이 SCSI 하드 드라이브이거나 혹은 여러 개의 하드 드라이브라면, 적절하게 make.fdisk를 호출하도록 이 스크립트를 편집하라.

#! /bin/sh

# A script to save certain meta-data off to the boot partition. Useful for
# restoration.

# Time-stamp: <2002-08-23 16:30:05 ccurley save.metadata>

# Copyright 2000 through the last date of modification, Charles Curley.

# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.

# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.

# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

# You can also contact the Free Software Foundation at http://www.fsf.org/


# 2002 07 01: Went to bzip2 to compress the archives, for smaller
# results. This is important in a 100MB ZIP disk. Also some general
# code cleanup.

# 2002 07 01: The function crunch will tar and BZIP2 the
# archives. This is cleaner than the old code, and has better safety
# checking.


# For more information contact the author, Charles Curley, at
# http://w3.trib.com/~ccurley/.


# Crunch: A function to compress the contents of a directory and put
# the archive onto the ZIP disk.

# The first parameter is the name of the archive file to be
# created. The backup location, $zip, will be prepended and the
# extension, "tar.bz2" will be appended.

# All following parameters will be taken as additional directories or
# files to be put into the archive.

function crunch {

if [ -z "$1" ] || [ -z "$2" ]	# Checks if parameter #1 or #2 is zero length.
then
   echo "-Parameter #1 or #2 is missing.-"  # Also if no parameter is passed.
   return 1
else
   local file=$1		# The archive file to create
   shift			# Discard the file name
   local dirs=$@		# The director[y|ies] to archive
   local tarcmd="tar -cjf"	# The tar command.

   $tarcmd  $zip/$file.tar.bz2 $dirs # do it!!

   error=$?			# Preserve the exit code

   if [ $error != 0 ]		# Did we fail?
   then				# Yes
      echo "Tar failed with error $error"
      echo $tarcmd $zip/$file.tar.bz2 $dirs
      exit $error		# return tar's exit code as ours
   fi

   return 0			# For error testing if needed.
fi
}

# Begin the main line code
export zip="/mnt/zip";		# Where we will put archives
#  export save="/mnt/save";

echo "saving hard drive info"
make.fdisk /dev/hda

# back up RPM metadata

echo "Verifying RPMs."

rpm -Va > /etc/rpmVa.txt

echo "Finished verifying RPMs; now mounting the ZIP drive."

# Make sure we have the ZIP drive mounted.
umount $zip
modprobe ppa			# Driver for 100MB parallel port ZIP disk
mount /dev/sda1			# It should have ext2fs on partition 1.

# clean it all out
rm -r $zip/*
mkdir $zip/lost+found

echo "Building the ZIP drive backups."

# These are in case we need to refer to them while rebuilding. The
# rebuilding process should be mostly automated, but you never
# know....

fdisk -l /dev/hda > $zip/fdisk.hda

ls -al /mnt > $zip/ls.mnt.txt
ls -al / > $zip/ls.root.txt

mkdir $zip/etc;
cp -p /etc/* $zip/etc

cd /

# Build our minimal archives on the ZIP disk. These appear to be
# required so we can restore later on.

crunch boot boot
crunch root root
crunch etc etc
crunch lib lib

crunch usr.sbin usr/sbin
crunch usr.bin usr/bin
crunch sbin sbin
crunch bin bin
crunch dev dev

# Now optional saves.

# arkeia specific:
# crunch arkeia usr/knox

# save these so we can use ssh for restore. *crack* for RH 7.0 login
# authentication.
crunch usr.lib usr/lib/*crack* usr/lib/libz* usr/lib/libssl* usr/lib/libcrypto* 

# save the scripts we used to create the ZIP disk and the ones we will
# use to restore it.
mkdir $zip/root.bin
cp -p /root/bin/* $zip/root.bin
rm $zip/root.bin/*~ $zip/root.bin/#*#

echo "Testing our results."
find $zip -iname "*.bz2" | xargs bunzip2 -t

# Not a normal part of the process: we duplicate the ZIP disk onto an
# NFS mount elsewhere.

#  echo "Backing the ZIP drive to the NFS mount."

#  umount $save
#  mount $save

#  rm -r $save/zip
#  mkdir $save/zip
#  cp -pr $zip $save

df -m

11.1.5. restore.metadata

이 스크립트는 일단계 복구로서 ZIP disk에서 metadata를 복구한다.

#! /bin/sh

# A script to restore the meta-data from the ZIP disk. This runs under
# tomsrtbt only after partitions have been rebuilt, file systems made,
# and mounted. It also assumes the ZIP disk has already been
# mounted. Mounting the ZIP disk read only is probably a good idea.

# Time-stamp: <2002-09-10 11:05:43 ccurley restore.metadata>

# Copyright 2000 through the last date of modification Charles Curley.

# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.

# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.

# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

# You can also contact the Free Software Foundation at http://www.fsf.org/

# 2002 07 01: Went to bzip2 to compress the archives, for smaller
# results. This is important in a 100MB ZIP disk. Also some general
# code cleanup.

# For more information contact the author, Charles Curley, at
# http://w3.trib.com/~ccurley/.


zip="/mnt";			# Where we mount the zip drive.
target="/target";		# Where the hard drive to restore is mounted.

ls -lt $zip			# Warm fuzzies for the user.

cd $target

# Restore the archived metadata files.
for archive in $( ls $zip/*.bz2 ); do
echo $archive
ls -al $archive
bzip2 -dc $archive | tar -xf -
done

# Build the mount points for our second stage restoration and other
# things.

# If you boot via an initrd, make sure you build a directory here so
# the kernel can mount the initrd.

for dir in mnt mnt/save mnt/zip mnt/cdrom mnt/floppy mnt/imports proc; do
mkdir $target/$dir
done

chmod a-w $target/proc		# Restore /proc's read-only permissions

# Restore the scripts we used to create the ZIP disk and the ones we will
# use to restore it. These should be the latest & greatest in case we had
# to do any editing during 1st stage restore.
cp -p $zip/root.bin/* $target/root/bin

# Now install the boot sector.
chroot $target /sbin/lilo -C /etc/lilo.conf

df -m

11.1.6. first.stage

This script runs the entire first stage restore with no operator intervention.

If you want make.dev.hda to check for bad blocks when it puts a file system on the partitions, use a "-c" command line option.

#! /bin/sh

# A master script to run the other, detailed scripts. Use this script
# only if you want no human intervention in the restore process. The
# only option is -c, which forces bad block checking during formatting
# of the partitions.

# Time-stamp: <2002-07-25 14:22:03 ccurley first.stage>

# Copyright 2002 through the last date of modification Charles Curley.

# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.

# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.

# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

# You can also contact the Free Software Foundation at http://www.fsf.org/

export blockcheck=$1;

if [ "$blockcheck" != "-c" ] && [ -n "$blockcheck" ]
then
    echo "${0}: automated restore with no human interaction."
    echo "${0}: -c: block check during file system making."
    exit 1;
fi

cd /mnt/root.bin		# just in case we aren't already where we should be.

for drive in $( ls make.dev.* ); do
    ./$drive $blockcheck;
done

restore.metadata

11.2. 2단계(Second Stage)

이 스크립트는 백업하거나 복구할 컴퓨터에서 실행한다.

11.2.1. back.up.all

이 스크립트는 NFS 마운트를 이용해서 다른 컴퓨터에 저장한다. tape 드라이브나 다른 매체에 저장하도록 할 수 있다.

#! /bin/sh

# Back up the entire system to another computer's drive. To make this
# work, we need a convenient chunk of disk space on the remote computer we
# can nfs mount as /mnt/save.

# Time-stamp: <2001-11-19 09:19:35 ccurley back.up.all>

# Copyright 2000 through the last date of modification Charles Curley.

# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.

# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.

# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

# You can also contact the Free Software Foundation at http://www.fsf.org/

# For more information contact the author, Charles Curley, at
# http://w3.trib.com/~ccurley/.

save="/mnt/save"

# Make sure it's there
umount $save
mount $save

cd /

rm $save/tester.tar.old.gz
mv $save/tester.tar.gz $save/tester.tar.old.gz

# save everything except /mnt, /proc, and nfs mounted directories.

time tar cf - / --exclude /mnt --exclude /proc --exclude $save\
    | gzip -c > $save/tester.tar.gz

11.2.2. back.up.all.ssh

이 스크립트는 back.up.all과 동일하게 동작한다. 단지 NFS 대신 ssh을 이용한다는 것이 다를 뿐이다.

#! /bin/sh

# Back up the entire system to another computer's drive. To make this
# work, we need a convenient chunk of disk space on the remote
# computer. This version uses ssh to do its transfer, and compresses
# using bz2. This means this script has to know more about the other
# computer, which does not make for good modularization.

# Time-stamp: <2001-11-19 09:19:48 ccurley back.up.all.ssh>

# Copyright 2000 through the last date of modification Charles Curley.

# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.

# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.

# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

# You can also contact the Free Software Foundation at http://www.fsf.org/

# For more information contact the author, Charles Curley, at
# http://w3.trib.com/~ccurley/.

save="/backs/tester"
backup_server="charlesc"

# rotate the old backups. Do it all in one line to minimze authentication overhead.
ssh $backup_server "rm $save/tester.tar.old.bz2; mv $save/tester.tar.bz2 \
    $save/tester.tar.old.bz2"

# save everything except /mnt, /proc, and squid directories.

time tar cf - / --exclude /mnt --exclude /proc --exclude /var/spool/squid\
    | ssh $backup_server "bzip2 -9 > $save/tester.tar.bz2"

11.2.3. restore.all

이 스크립트는 back.up.all 스크립트를 이용해서 백업한 경우 복구하기 위해 사용하는 것이다.

#! /bin/sh

# A script to restore all of the data from an nfs mount. This is our final
# stage restore.

# Time-stamp: <2001-11-19 09:21:22 ccurley restore.all>

# Copyright 2000 through the last date of modification Charles Curley.

# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.

# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.

# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

# You can also contact the Free Software Foundation at http://www.fsf.org/

# For more information contact the author, Charles Curley, at
# http://w3.trib.com/~ccurley/.

export save="/mnt/save"

mount $save

cd /
gunzip -dc $save/tester.tar.gz | tar -xpkf -

rm /var/run/*.pid

lilo

11.2.4. restore.all.ssh

이 스크립트는 back.up.all.ssh을 이용하여 백업했을 때 사용하는 복구 스크립트이다.

#! /bin/sh

# A script to restore all of the data using ssh and bunzip2. This is
# our final stage restore.

# Copyright 2000 through the last date of modification Charles Curley.

# Time-stamp: <2001-11-19 09:21:33 ccurley restore.all.ssh>

# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.

# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.

# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

# You can also contact the Free Software Foundation at http://www.fsf.org/

# For more information contact the author, Charles Curley, at
# http://w3.trib.com/~ccurley/.

save="/backs/tester/"
backup_server="charlesc"

cd /

ssh $backup_server "cat $save/tester.tar.bz2" | bunzip2 | tar -xpkf -

rm /var/run/*.pid

lilo

11.3. 백업 서버 스크립트(Backup Server Script)

위의 SSH 스크립트는 보안에 있어 문제가 있을 수 있다. 방화벽 위에서 스크립트들이 실행된다면, 방화벽은 SSH을 통하여 백업 서버에 접근을 허가해야만 한다. 이 경우에 있어, 영리한 크래커는 백업서버를 크랙할 수도 있을지 모른다. 백업서버에서 백업과 복구 스크립트를 실행하고, 백업 서버로 하여금 방화벽에 접근하도록 하는 것이 좀더 안전한 방법이 될 수 있을 것이다. 이상이 왜 이 스크립트들이 존재하는 가에 대한 이유이다. 이것들을 get.xrestore.x로 이름을 바꾸어라. 여기서, x는 대상 컴퓨터의 이름이다. 대상 컴퓨터의 호스트 이름을 사용할 수 있도록($target 변수의 초기화) 스크립트들을 편집하거나 명령어 줄에 인수로 사용할 수 있도록 스크립트를 다시 써야 한다.

이 스크립트들은 단지 일단계 백업과 복구만이 아니라, 대상 컴퓨터를 완전히 백업하고 복구한다. 또한 만약 오류가 있는 ZIP disk를 교체할 필요가 있을 경우에, get.tester 스크립트는 ZIP disk 또한 백업한다.

나는 이 스크립트들을 주기적으로 사용한다.

11.3.1. get.tester

#! /bin/sh

# Back up another computer's drive to this system. To make this work, we
# need a convenient chunk of disk space on this computer. This version
# uses ssh to do its transfer, and compresses using bz2. This version was
# developed so that the system to be backed up won't be authenticated to
# log onto the backup computer. This script is intended to be used on a
# firewall. You don't want the firewall to be authenticated to the backup
# system in case the firewall is cracked.

# Time-stamp: <2002-08-23 16:12:35 ccurley get.tester>

# Copyright 2000 through the last date of modification Charles Curley.

# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.

# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.

# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

# You can also contact the Free Software Foundation at http://www.fsf.org/

# For more information contact the author, Charles Curley, at
# http://w3.trib.com/~ccurley/.

# 2002 07 01: We now set the path on the target to the zip drive with
# a variable. This fixes a bug in the command to eject the zip disk.

# 2002 07 01: The zip disk archives are now in bzip2 format, so this
# script has been changed to reflect that.



# The host name of the computer to be backed up.
target=tester
zip=/mnt/zip

echo Backing up $target

echo Aging the ZIP disk backups.

rm -r $target.old.zip

mv $target.zip $target.old.zip

ssh $target "modprobe ppa ; mount -r $zip"

echo Copying the ZIP disk.

# -r for recursive copy, -p to preserve times and permissions, -q for
# quiet: no progress meter.

scp -qpr $target:$zip $target.zip

du -hs $target.zip


echo Aging the archives

rm $target.tar.old.bz2

mv $target.tar.bz2 $target.tar.old.bz2


echo Backing up $target to the backup server.

ssh $target tar -cf - / --exclude /mnt --exclude /proc --exclude /var/spool/squid\
    | bzip2 -9 | cat > $target.tar.bz2

echo Testing the results.
find . -iname "*.bz2" | xargs bunzip2 -t

ssh $target "eject $zip"

11.3.2. restore.tester

#! /bin/sh

# A script to restore all of the data to tester via ssh. This is our final
# stage restore.

# Time-stamp: <2001-11-19 09:22:01 ccurley restore.tester>

# Copyright 2000 through the last date of modification Charles Curley.

# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.

# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.

# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

# You can also contact the Free Software Foundation at http://www.fsf.org/

# For more information contact the author, Charles Curley, at
# http://w3.trib.com/~ccurley/.

# The host name of the computer to be restored.

target=tester

bunzip2 -dc $target.tar.bz2 | ssh $target "cd / ; tar -xpkf - "

ssh $target lilo