This content is submitted by a BigAdmin user. It has not been reviewed for technical accuracy by Sun Microsystems, though it may have been lightly edited to improve readability. If you find an error or would like to comment on the article, please contact the submitter or use the comment field at the bottom of the article.
Community submissions may not follow Sun trademark guidelines. For information on Sun trademarks, please see http://www.sun.com/suntrademarks/.
Scripts for Backing Up and Restoring ZFS File Systems in the Solaris 10 OS
Victor Feng, October 2007
Introduction
This tech tip provides an overview of two scripts for the Solaris 10 Operating System: a zfsdumpd.sh script for backing up ZFS file systems and
a zfsrestored.sh script for restoring ZFS file systems.
As you know, UFS has ufsdump and ufsrestore utilities. ZFS
is a great file system, but it does not have equivalent zfsdump and zfsrestore
utilities. If your environment has 100 users, and each user has their own file system, using the zfsdumpd.sh and
zfsrestored.sh scripts can save you a lot of time backing up and restoring those 100 ZFS file systems.
Here's the source code for the two scripts. Please rename the files so that the extension is .sh instead of .txt.
-d backup_dir specifies the directory in which to back up the file system.
The default backup directory is /var/zfsbk on the disk, which can be changed
through $DIR in the zfsdumpd.sh script.
-r causes the script to recursively back up the file system's descendants.
-z zfs specifies which one file system should be backed up. Without
the -z option, the script backs up every file system.
The zfsdumpd.sh script does not accept positional parameters. If there are any positional parameters,
the total number of parameters will not equal the number of command-line options and the script will exit when the following
script code is executed:
The zfsdumpd.sh script dumps file systems to disk using the zfs send command.
If -z zfs is not specified, $zfs will be empty
when the following script code is executed:
(if [ "X$zfs" != X ]),
In such a case, Create_BackupSnapshotsAll is called to create and back up a snapshot for each file system.
Create_BackupSnapshotsAll destroys each existing snapshot first. The snapshot format is
filesystem@today's_date, for example, tank/home/bo@20070910.
If -z zfs is specified, Create_BackupSnapshots is
called to create and back up a snapshot for the specified file system. Any existing snapshot is deleted first.
If -r is specified, Create_BackupSnapshots creates and backs up a snapshot
for each descendant file system. Any existing snapshots are deleted first.
For each snapshot that is created, for example, tank/home/bo@20070910,
GetBackupfileprefixFromSnapshot determines the backup file prefix in the format
path_to_filesystem.today's_date, for example,
tank_home_bo.20070910. Before the backup is created in /var/zfsbk, the script
deletes any existing file that has the format path_to_filesystem.*,
for example, tank_home_bo.*.
for snapshot in $SNAPSHOTS; do
file_prefix=`GetBackupfileprefixFromSnapshot "$snapshot"`
if find "$DIR" | grep "${file_prefix}\." >/dev/null 2>&1; then
rm ${DIR}/${file_prefix}.*
fi
if zfs send "$snapshot" > ${DIR}/${file_prefix}.$mydate; then
myzfs=`echo $snapshot | awk -F@ '{print $1}'`
echo "$myzfs is backed up as ${DIR}/${file_prefix}.$mydate"
fi
done
Examples
Example 1: Back up each file system in every storage pool in the system.
# zfsdumpd.sh
Example 2: Recursively back up each file system in the storage pool tank.
# zfsdumpd.sh -r -z tank
Example 3: Recursively back up tank/home.
# zfsdumpd.sh -r -z tank/home
Example 4: Back up tank/home.
# zfsdumpd.sh -z tank/home
Explanation of the zfsrestored.sh Script
Usage
zfsrestored.sh [-d backup_dir] [-n] [-r] [-z zfs]
where:
-d backup_dir specifies the directory from which to restore the file system.
The default restore directory is /var/zfsbk on disk, which can be changed
through $DIR in the zfsrestored.sh script.
-n specifies to not back up the file system to a temporary directory before restoring. The
default temporary backup dir is /var/zfsbk_tmp, which can be changed through $DIRTMP
in the zfsrestored.sh script.
-r causes the script to recursively restore the file system's descendants.
-z zfs specifies which one file system should be restored. Without
the -z option, the script restores every file system.
The zfsrestored.sh script restores file systems from the disk using the zfs receive command.
If -z zfs is not specified, $zfs will be empty
when the following script code is executed:
(if [ "X$zfs" != X ]),
In such a case, then each file system is restored. For each file system in each storage pool,
CheckBackupNeeds checks to see if there is a backup. If not, the
zfsrestored.sh script displays a "backup needed" message and exits.
for zfs in $POOLS; do
ZFSs=`zfs list -t filesystem -o name -r $zfs | grep -vw NAME`
CheckBackupNeeds
done
If -n is not specified, (that is, $nobackup equals 1), the
zfsdumpd.sh script is called to dump all the file systems to a temporary directory in case you want to roll
back. For the root file system in each pool, the script destroys the descendants, then restores the root file system and its
descendants using RestoreBasedonCurrentZfs.
[ $nobackup -eq 1 ] && zfsdumpd.sh -d $DIRTMP
for zfs in $POOLS; do
ZFSs=`zfs list -t filesystem -o name -r $zfs | grep -vw NAME`
zfs destroy -r $zfs
RestoreBasedonCurrentZfs
done
RestoreBasedonCurrentZfs calls RestoreSingleCurrentZfs to restore
a file system and its descendants.
The root file system is not restored back to its original place, because whenever a pool is created, a
corresponding root file system is created for it. So a good practice is to not put anything in the root file system
except for creating the file system in it.
For a file system, for example, tank/home/bo,
GetBackupfileprefixFromZfsname gets the backup file's prefix (tank_home_bo).
Then the script looks for the backup file using the file prefix, and it restores the backup snapshot.
RestoreSingleCurrentZfs ()
{
each_zfs=$1
if echo $POOLS | grep -w $each_zfs > /dev/null; then
echo "Warning: $each_zfs is not allowed to restore. You may
use zfs receive $each_zfs/xxx"
else
file_prefix=`GetBackupfileprefixFromZfsname $each_zfs`
BACKUPSNAPSHOT=`find "$DIR" | grep "$file_prefix\."`
if zfs receive $each_zfs < $BACKUPSNAPSHOT; then
echo "$each_zfs is restored from $BACKUPSNAPSHOT"
fi
fi
}
If -z zfs is specified, we need to identify some illegal file systems, for example, /tank/home/bo and tank/home/bo.
if echo $zfs | egrep "^/|/$" > /dev/null
then
echo "The format of zfs is tank/home/norma"
exit 2
fi
If -r is used with -z zfs, the zfsrestored.sh script
checks to see whether the file system exists. 1) If it exists, the script checks to see if all the file systems have a backup.
2) If it does not exist, the script calls RestoreBasedonBackupZfss to restore whatever it could find
in the default backup location.
if [ $recursive -eq 0 ]
then
if ZFSs=`zfs list -t filesystem -o name -r $zfs 2>/dev/null |
grep -vw NAME`
then
CheckBackupNeeds
[ $nobackup -eq 1 ] && zfsdumpd.sh -d $DIRTMP -r -z $zfs
zfs destroy -r $zfs
if RestoreBasedonCurrentZfss; then
echo "\nYou may empty $DIRTMP after checking the
restoration."
fi
else
RestoreBasedonBackupZfss $zfs
fi
else
RestoreBasedonBackupZfss first gets the backup file prefix for the file system, for example,
tank_home_bo. Then it searches the backup snapshot file for the file system and all of its descendants
using prefixes with the format tank_home_bo.* and tank_home_bo_*.
Then GetZfsnameFromSnapshot gets the file system (for example, tank/home/bo) from
its backup snapshot file (for example, tank_home_bo.20070910). Finally, the file system
(for example, tank/home/bo) is restored from the backup file (for example,
tank_home_bo.20070910). If there is no backup file, the script displays an error and exits.
RestoreBasedonBackupZfss ()
{
file_prefix=`GetBackupfileprefixFromZfsname $1`
if find "$DIR" | egrep "${file_prefix}_|${file_prefix}\."
>/dev/null 2>&1
then
for snapshot in `find "$DIR" | egrep "${file_prefix}_|
${file_prefix}\."`
do
zfsname=`GetZfsnameFromSnapshot $snapshot`
if zfs receive $zfsname < "$snapshot"; then
echo "$zfsname is restored from $snapshot."
fi
done
else
echo "Error: Backup file $file_prefix.* does not exist in $DIR"
exit 2
fi
}
If -r is used with -z zfs and the file system (for example,
tank/home) and its backup exist, the script renames the file system (for example,
tank/home) to something else. The file system cannot be destroyed, because it might have descendants.
After the file system is restored, its descendants are renamed back under it, for example, from
tank/home_$pid. The variable zfs_c makes sure that only
those immediate descendants of tank/home_$pid, for example, tank/home/bo, are
renamed. This is because sub-immediate descendants, for example, tank/home/bo/projects, are automatically renamed.
If a descendant file system has exactly one more field than the parent file system has, it is the immediate descendant file system.
pid=$$
zfs rename $zfs ${zfs}_$pid
RestoreSingleCurrentZfs $zfs
zfs_c=`echo $zfs | nawk -F'/' '{print NF}'`
zfs_c=`expr $zfs_c + 1`
for zpid in `zfs list -t filesystem -o name -r ${zfs}_$pid |
grep ${zfs}_${pid}/`; do
if [ `echo $zpid | nawk -F'/' '{print NF}'` -eq $zfs_c ]; then
zfs rename $zpid `echo $zpid | sed "s,^${zfs}_$pid,$zfs,"`
fi
done
zfs destroy -r ${zfs}_$pid
Examples
Example 1: Restore each file system in every storage pool in the system.
# zfsrestored.sh
Example 2: Recursively restore each file system in the storage pool tank.
# zfsrestored.sh -r -z tank
Example 3: Recursively restore tank/home.
# zfsrestored.sh -r -z tank/home
Example 4: Restore tank/home.
# zfsrestored.sh -z tank/home
Example 5: Restore the file systems without making a temporary backup.
# zfsrestored.sh -n
The information and links on this page have been provided by a BigAdmin user. The submitter is solely responsible for such information and links. Sun is not responsible for the availability of external sites or resources, and does not endorse and is not responsible or liable for any content, advertising, products, or other materials on or available from such sites or resources. Sun will not be responsible or liable, directly or indirectly, for any actual or alleged damage or loss caused by or in connection with use of or reliance on the information posted here, or goods or services available on or through any external site or resource.
Comments (latest comments first)
Discuss and comment on this resource in the BigAdmin Wiki
Unless otherwise licensed, code in all technical manuals herein (including articles, FAQs, samples) is provided under this License.