Backup
Scripts from UnixReview.com, 3rd Edition
Edited by Ed Schaefer
I still host the monthly Shell Corner at UnixReview.com. This
third edition of "Backup Scripts" features scripts from three pillars
of the comp.unix.shell newsgroup. If you've posted to that newsgroup,
Heiner Steven, Michael Wang, or Chris F. A. Johnson may have answered
your question. The first script described in this article creates
a local archive of files on a remote host. The second script creates
a Solaris alternative backup boot disk, and the third script automatically
extracts files of various archive types into the current directory.
Backup by Heiner Steven
My script, "Backup" (Listing 1), creates an archive of files and
directories on a remote system, writing them to a local tape drive
(e.g., a DAT or DLT device). Backup is written in a portable Bourne-shell
style, which is understood by most derived shells (e.g., bash, ksh,
and ksh93). With slight modifications, it runs on Solaris and Linux.
For example, assume you have a local system (named "newton"),
which possesses a DAT tape and can be used to store backups. Executing
this command:
backup darwin
is sufficient to write a cpio archive of all files on the remote
host "darwin" to the local tape device (e.g., /dev/rmt/0). The command:
backup darwin etc usr/local
saves only the "/etc" and "/usr/local" directory hierarchies on host
"darwin". Observe that all relative path names not starting with a
slash ("/") are interpreted relative to the remote root ("/") directory.
So how does it work? Backup uses the remote shell, rsh (on
some systems called remsh), to run the following commands on
the remote host:
cd /
find * -xdev -print | cpio -o
The find command creates a list of the local files on host
"darwin". -xdev ensures that find does not traverse
non-local (e.g., NFS) mounted directories. cpio then reads
the list, creates a cpio archive, and writes it to standard
output. The remote shell copies this output from the remote host "darwin"
to the local host "newton", where I set up the copy process to the
tape device.
Although I might have used cat > /dev/rmt/0, some tapes
need the input in 10-k blocks, so I used:
dd of=/dev/rmt/0 bs=10k
which blocks output in exactly the required method. Putting everything
together, I get the following (simplified) command line:
rsh darwin 'cd /; find * -xdev -print | cpio -o' |
dd of=/dev/rmt/0 obs=10k
The rsh command functions only if there is an entry in the
target system's ".rhosts" file allowing the backup script to log-in
non-interactively. Alternatively, ssh can be used in the place
of rsh (see below).
The previous command line copies remote files and directories
to a local tape. What if I want to restore the data? The following
command line reads a cpio archive from a local tape and extracts
the files and directories on the remote system "darwin":
dd if=/dev/rmt/0 ibs=10k |
rsh darwin 'cd /; cpio -ivdu'
The script can easily be configured and modified for different purposes.
If you prefer the Secure Shell, ssh, over rsh, just
uncomment the lines in the script marked Use ssh. If you want
to use tar, replace find * -print | cpio -o with tar
cvf - *. However, I prefer the find command's flexibility
and file selection options (e.g., -mtime -7, to list only files
that have been modified in the last 7 days, or -newer .timestamp
to process only files newer than the file ".timestamp").
Copyroot by Michael Wang
If you manage Solaris systems, you know the importance of the
boot disk. To protect the boot disk, administrators have opted to
use online mirrored disks in addition to regular backups. The great
advantage of online mirrors is hardware failure protection; when
one of the mirrored disks fails, the system will still be up and
running.
However, if there is a file error, file system corruption, or
a human error, both of the mirrored disks are at fault. It is slow
and difficult to restore from backup tape, especially when the backup/restore
software is unavailable because of an error.
I introduce a simple, different approach, which may be used instead
of, or in addition to, online mirrors. Copyroot (Listing 2) creates
a Solaris alternative backup boot disk. Rather than creating an
online mirror, copyroot makes a delayed, "offline" mirror. Changes
on the primary disk do not immediately propagate to the backup boot
disk, providing a chance to correct the error, or fall back to the
last known good OS.
The backup boot disk does not prevent the server from going down.
When the primary boot disk crashes, however, you can simply type
a boot command to boot from the backup disk. You can also automatically
boot when the "boot-device" is set to multiple boot disks.
Solaris allows you to define a device alias using "nvalias", for
example:
nvalias bkupboot /pci@1f,4000/scsi@3/disk@8,0
The above alias allows this boot command:
boot bkupboot
which boots the system from the backup boot disk. The boot-device
can be defined to have multiple boot disks with, for example:
ok> setenv boot-device primboot bkupboot
Whenever a server needs to be shut down for maintenance tasks, I always
perform the ritual of boot bkupboot, shutdown, boot
to verify the backup boot disk. Also, you do not need to choose between
using online mirrors and the backup boot disk; if you can afford a
third disk, you can have both.
Copyroot was written in the Solaris 2.3 days, and works all the
way up to Solaris 9. I recently updated it to support a configuration
where the primary boot disk is mirrored using Solaris Volume Manager,
which is part of Solaris 9.
I did not test copyroot for creating a boot disk under Veritas
Volume Manager, but it should work. However, one of the Sun BluePrints
papers (see References) "strongly discourages" Veritas Volume Manager
on boot disk in favor of Solaris Volume Manager, citing that "VERITAS
volumes do not, by default, correspond to partitions", and mentions
"extra complications".
Now, let's review how copyroot works, following the program flow,
and emphasizing the major points.
Setting Up Working Environment
The shell used is ksh93d, which is part of Solaris distribution
at least since Solaris 2.6. During the recent update, some new features
of ksh93 came in handy. Following shell definition, I always define
PATH, which solves the "can run on command line, but not on cron"
problem. builtin -d uname removes uname as a ksh93d built-in
command, forcing uname to be /bin/uname. The built-in uname -i,
which previously delivered unexpected results, is fixed in the recent
ksh93 shell.
Lines 15-24 are generic; they set up the OPT ("OPT Power Tools")
directory structure, one of my earlier designs:
- All jobs reside in a common directory ($my_dir).
- The configuration files, or associated programs, if any, are
in the same directory as jobs, and can be derived from the job
names ($my_name). For example, the configuration corresponding
to $my_name would be $my_name.cf.
- The log directory $my_logdir for each job is $my_dir/log/$my_name.
- Log file ($my_logfile) has the time_stamp appended, and the
alphabetic order (ls listing) corresponding to the time order.
- I redirect all the standard error and output to the log file,
which catches all the errors -- especially unexpected errors.
- Log files are cleaned by the program itself. The retention
period is defined in the configuration file, or set to the default
value.
Sourcing the Configuration File
Copyroot needs some information to start, which is obtained by
sourcing the configuration file, copyroot.cf. Here is a configuration
file sample:
machine_name="ziqi" # for verification purpose
p_boot=$( # primary boot disk partitions
print /dev/dsk/c0t0d0s0
print /dev/dsk/c0t0d0s1
print /dev/dsk/c0t0d0s3
print /dev/dsk/c0t0d0s4
print /dev/dsk/c0t0d0s6
)
b_boot=$( # backup boot disk partitions
print /dev/dsk/c0t8d0s0
print /dev/dsk/c0t8d0s1
print /dev/dsk/c0t8d0s3
print /dev/dsk/c0t8d0s4
print /dev/dsk/c0t8d0s6
)
backup_dir="/apps2" # optional directory to hold boot disk backup
The variables defined in the configuration file are:
- Define the machine_name. The purpose is to compare the definition
with output from uname -n, making sure copyroot runs on
the correct machine.
- Define the device names for the primary boot disk, and define
the backup boot disk. Copyroot assumes that the first item in
the list is the device name for the root file system, which every
Solaris sytem must have. The second item is the dedicated swap
partition. If you do not have one, or if it is not on the boot
disk, use "-" as a placeholder. The primary device names and backup
device names should correspond one-to-one.
- Reverse copy is done simply by swapping the definition of p_boot
and b_boot. This is needed when the primary boot disk crashes
and is replaced.
- "backup_dir" is an optional directory to hold the boot disk
backup, which I will clarify later.
When the boot disk is under the Solaris Volume Manager, the definition
of p_boot looks like this:
p_boot=$(
print /dev/md/dsk/d0
print /dev/md/dsk/d1
print /dev/md/dsk/d3
print /dev/md/dsk/d4
print /dev/md/dsk/d6
)
Checking the Run Machine
Ensure the script executes only on the box where you want it to
run. To disable the program, simply define machine_name as something
that does not match uname -n. This might be an option, for
example, when the OS on the primary boot disk is upgraded, and you
want the backup boot disk to still have the old OS for an extended
period of time (see lines 37-40).
This erroring out also reminds you to change the machine_name
back to uname -n, after you feel the upgrade is okay.
Checking the Mounted File Systems
To perform duplication using ufsdump and ufsrestore, mount the
backup disk slices under /copyroot. Initially, nothing should be
mounted under /copyroot. If there is, perhaps something else is
mounted. Also, the backup disk slices should not be mounted at all.
If these conditions happen, something is wrong and copyroot should
not continue (see lines 42-46).
Performing the Dry Run
Lines 48-67 perform the dry run. Copyroot cycles through each
slice except the swap slice, running ufsdump on each slice, and
outputting to /dev/null, or a backup file under $backup_dir if it
is defined in the configuration file.
Copyroot uses ufsdump to check the primary boot disk. If the primary
disk has a corruption, it most likely shows up in a dry run. I then
terminate the program, preventing the corruption to propagate to
the backup disk. This is not a perceived caution, but a lesson learned
the hard way.
Since I do not know what error messages ufsdump may produce, I
parse the messages, line by line, checking for known, expected output.
Anything other than expected output is considered an error, and
the program terminates immediately. This is more reliable than checking
the exit code.
Saving the ufsdump file, and using it later on for restore not
only avoids the need to read the boot disk twice, but also is safer
because the restore uses the verified backup, instead of ufsdump
output on the fly.
Partitioning Backup Disk
A prerequisite of using copyroot is partitioning the backup disk,
which needs to be partitioned only initially, and in the rare case
when the primary disk is repartitioned. If the backup disk is of
the same size as the primary, you can, and should, partition the
backup disk as the primary. The syntax is shown in a comment (line
69) or you can do it manually.
Copyroot, which uses ufsdump and ufsrestore, does not require
the backup disk be the same size or have the same partitions as
the primary. It only requires the backup partitions be large enough
to hold the same amount of data as the primary.
Performing the Actual Run
Lines 71-106 create the backup disk. For each slice of the backup
disk except the swap partition, execute newfs to make a new UFS
file system, and check it with fsck (lines 77-79). The fsck may
not be necessary for newly created file systems, but won't hurt.
Next, mount the slice and verify the mount directly (lines 81-82).
I ufsrestore every slice, skipping the swap partition, from the
primary to the backup, using ufsdump output on the fly or the saved
ufsdump file (lines 84-88).
The root file system needs special attention as follows. The vfstab
file contains the boot disk device name for boot strapping purposes.
The file on the backup boot should contain the device name of the
backup disk instead of the primary. Code lines 91-97 perform the
changes.
If the primary boot disk is mirrored using Solaris Volume Manager,
the /etc/system file contains a line added by "metaroot":
rootdev:/pseudo/md@0:0,0,blk
which defines the root device to be the mirrored volume. This line
needs to be commented out in the backup /etc/system (lines 99-101).
Each slice is synchronized from the primary, /copyroot is umounted,
and the partition is fscked again -- just to be sure.
On a Sun E250 with 2x300MHz CPU, 896 MB memory, all SEAGATE ST318405LC
disks, running Solaris 9 full installation, copyroot requires about
12 minutes to back up the primary disk to the $backup_dir on the
third disk, and restore to the backup boot disk. Although relatively
short, the synchronization process is inefficient and vulnerable.
Considering most of the data is static, I'm seeking a better method.
Install the Boot Block
Last, we install the boot block, otherwise it won't boot (line
108). (For those familiar with Linux, this is analogous to lilo,
or grub).
In conclusion, copyroot creates a backup boot disk using a simple,
standard method, which provides protection for the primary disk
data. In case of hardware failure, copyroot reduces downtime by
booting from the backup boot disk. It can be used with Volume Manager
mirrored boot disk to provide both online availability and data
protection. Future versions of copyroot, if any, will be found at
http://www.unixlabplus.com/unix-prog/copyroot.
References
Erik Vanden Meersch and Kristien Hens, October 2002. Configuring
Boot Disks with Solaris Volume Manager Software -- http://www.sun.com/solutions/blueprints/0402/solstice.pdf
Sun Microsystems, 2002. Solaris Volume Manager Administration
Guide -- http://docs.sun.com/db/doc/806-6111
John S. Howard and David Deeths, 2001. Boot Disk Management:
A Guide for the Solaris Operating Environment, Prentice Hall
PTR.
Unpack by Chris F. A. Johnson
Backups come in all shapes and sizes, created on many different
platforms with many different archiving tools and compressors. To
extract the files, there are just as many different utilities, though
some can handle more than one type of archive. To make life more
interesting, the same type of archive file may have different suffixes
(e.g., .tar.gz and .tgz are the same thing).
While it's not difficult to remember which archive utility goes
with which type of file, or even to remember which is or is not
installed on the current system, why not let the computer do it
for you? I wrote a short script to do just that. The result is unpack.
Now, whatever the format, I just type "unpack FILENAME.WHATEVER"
and the files are extracted under the current directory.
Any number of archives files can be specified on the command line,
and they don't all have to be the same type -- you can mix zip files
with gzip files with bzip2 files with whatever other format you
have.
The script is very simple -- a case statement within a "for" loop.
I don't remember ever using more than a single file on the command
line, but the script supports more. Each type of file is recognized
by case's pattern-matching capability; different forms for the same
type of file are handled on the same line.
The script is written to be as portable as possible. To that end,
it does not use the "z" option to tar, since not all versions of
the program include it. Ditto for "j", and its older equivalent,
"y". Instead, gunzip (or bunzip2) is called with the "-c" option
and the output piped through a generic tar command.
There are many enhancements that could be made to unpack, including
options to unpack in a different directory, to select silent or
verbose operation, or to customize error messages when a file is
not found or a program such as bzip2 is not installed. However,
I'm not likely to bother with those unless, of course, a situation
arises where I really need such a feature.
The only enhancement I am likely to add is other archive formats,
such as cpio, pax, and perhaps various Amiga archive formats. If
you want to add something to unpack, go right ahead (and please
send me a copy).
Heiner Steven is a Unix kernel programmer working in the area
of TCP/IP networking protocols. When he's not busy programming,
reading, riding his bicycle, making music, or playing with his son,
he works on his "SHELLdorado" shell scripting site: http://www.shelldorado.com/.
Michael Wang earned Master Degrees in Physics (Peking) and
Statistics (Columbia). Currently, he is applying his knowledge to
Unix systems administration, database management, and programming.
He can be reached at: xw73@columbia.edu.
After 20 years in magazine and newspaper publishing, variously
as writer, editor, graphic designer, and production manager, Chris
F.A. Johnson now earns his living composing cryptic crossword puzzles,
teaching chess, and dabbling in Unix systems administration and
programming. He can be reached at: cfaj@freeshell.org.
Ed Schaefer is a frequent contributor to Sys Admin.
He is a software developer and DBA for Intel's Factory Integrated
Information Systems, FIIS, in Aloha, Oregon. Ed also hosts the UnixReview.com
monthly Shell Corner column. He can be reached at: shellcorner@comcast.net.
|