Cover V12, i12

Article
Listing 1
Listing 2
Listing 3

dec2003.tar

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.