let's make a flash archive of a system over nfs shall we?
sure.
mkdir /tmp/flar_archive ; mount nfsserver:/vol/flar_archive /tmp/flar_archive
flarcreate -S -n system /tmp/flar_archive/system.flar
easy. what is this flarcreate of which you speak? throwing errors? see script after.
flarcreate
#!/bin/ksh
#
#ident "@(#)flarcreate.sh 1.7 04/12/08 SMI"
#
# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
########################################
# #
# flarcreate -- Create a Flash Archive #
# #
########################################
TEXTDOMAIN=SUNW_INSTALL_FLASH
export TEXTDOMAIN
# list of required utilities. If you add any to this
# list, be sure to also add it to the $UTIL_LIST variable below!
AWK="/usr/bin/awk"
SED="/usr/bin/sed"
DF="/usr/sbin/df"
RM="/usr/bin/rm"
CPIO="/usr/bin/cpio"
COMPRESS="/usr/bin/compress"
WC="/usr/bin/wc"
CAT="/usr/bin/cat"
UNAME="/usr/bin/uname"
FIND="/usr/bin/find"
TOUCH="/usr/bin/touch"
MT="/usr/bin/mt"
DD="/usr/bin/dd"
ID="/usr/bin/id"
LS="/usr/bin/ls"
UTIL_LIST="$AWK $SED $DF $RM $CPIO $COMPRESS $WC $CAT $UNAME $FIND $TOUCH $MT $DD $ID $LS"
##############################################################
# Function find_utils makes sure required utilies exist.
##############################################################
find_utils_or_exit ()
{
for i in $UTIL_LIST ; do
if [ ! -x $i ] ; then
print_error_and_exit "$(gettext "Required utility %s is not available.")" $i
fi
done
}
##############################################################
# Function print_error_and_exit prints a formatted message
# to stderr prefixed with ERROR: and new-lined, and exits 1.
##############################################################
print_error_and_exit ()
{
typeset format=$1
shift
typeset values=$*
printf "$(gettext 'ERROR:') ${format}\n" $values >&2
exit 1
}
##############################################################
# Function print_message prints a formatted message to stderr
##############################################################
print_message ()
{
typeset format=$1
shift
typeset values=$*
printf "${format}\n" $values >&2
}
###############################################################
# Function print_usage_and_exit does just that
###############################################################
print_usage_and_exit ()
{
# Remember to update the usage in flar if you update this one
typeset myname=`basename $0`
print_message "$(gettext "Usage:")"
print_message "$myname $(gettext '-n name [-R root] [-H] [-S] [-c] [-t [-p posn] [-b blocksize]]')"
print_message " $(gettext '[-i date] [-u section [-d path ]] [-U key=value] [-m master]')"
print_message " $(gettext '[-f [ list_file | - ] [-F]]')"
print_message " $(gettext '[-a author] [-e descr | -E descr_file] [-T type]')"
print_message " $(gettext '[[-x exclude_dir/file][-x exclude_dir/file]...] [-X list_file]')"
print_message " $(gettext '[[-y include_dir/file [-y include_dir/file]...]')"
print_message " $(gettext '[-z filter_list_file]')"
print_message " $(gettext 'archive')"
exit 1
}
##############################################################
# Function print_error_and_usage prints a formatted message to stderr
# with ERROR: and calls print_usage_and_exit
##############################################################
print_error_and_usage ()
{
typeset format=$1
shift
typeset values=$*
printf "$(gettext 'ERROR:') ${format}\n" $values >&2
print_usage_and_exit
}
##############################################################
# Functions dial(), start_dial(), stop_dial(), and cleanup()
# implement a spinner of |, /. -, and \. dial() runs in the
# background. Use of traps is critical to avoid spinning after
# user has Control-C'd.
##############################################################
dial()
{
typeset state=0
trap - EXIT INT # Set trap to ignore
while : ; do
case $state in
0)
echo "|\b\c" # top-bottom
state=1
;;
1)
echo "/\b\c" # upper right, lower left
state=2
;;
2)
echo "-\b\c" # left-right
state=3
;;
3)
echo "\\" "\b\b\c" # upper left, lower right
state=0
;;
esac
sleep 1
done
}
start_dial()
{
[[ $QUIET = $YES ]] && return
dial & # Start in background
DIALPID=$! # Get pid, for killing
trap "cleanup 1" EXIT INT # Set trap
}
stop_dial()
{
[[ $QUIET = $YES ]] && return
trap "" EXIT INT
kill $DIALPID >/dev/null 2>&1
DIALPID=
echo " \b\c"
}
cleanup()
{
typeset exitcode=$1
if [[ ! -z "$DIALPID" ]] ; then
kill $DIALPID
fi
if [[ -x $hash_file ]] ; then
${RM} -f $hash_file
fi
exit $exitcode
}
#####################################################################
# Function get_platforms makes a string for the content_architectures
# identification line. It prints the string, so the caller should
# get the string as $(get_platforms).
#####################################################################
get_platforms ()
{
typeset file="var/sadm/system/admin/.platform"
typeset entry=
typeset line=
typeset values=
# if there is no $root_directory, then the following argument
# to grep will be relative to /. Also, we aren't interested
# in any error output from grep, all we care is that it failed,
# so ignore stderr.
values=$(grep "^PLATFORM_GROUP" $root_directory/$file 2> /dev/null)
if [[ $? -ne 0 ]]; then
print $(${UNAME} -m)
return
fi
for entry in $values ; do
[[ ! -z $line ]] && line="${line},"
line="${line}${entry#PLATFORM_GROUP=}"
done
print $line
}
######################################################
# Function size_archive implements the sizing feature
# of flarcreate.
######################################################
size_archive()
{
# Set up
archive_size=0
print_message "$(gettext "Determining the size of the archive...")"
start_dial
archive_size=$(gen_archive | \
${WC} -c |${AWK} '{print $1}')
status=$?
stop_dial
# Clean up
if [[ $status != 0 || -z "$archive_size" || $archive_size -eq 0 ]]; then
print_error_and_exit "$(gettext "Unable to find size of intended archive.")"
fi
# Print the size
if [[ ${#archive_size} -gt 9 ]] ; then
unit="GB"
div=1073741824
elif [[ ${#archive_size} -gt 6 ]] ; then
unit="MB"
div=1048576
else
unit="KB"
div=1024
fi
intnum=$(echo $archive_size / $div |bc)
fracnum=$(echo $archive_size / \( $div / 100 \) % 100 |bc)
print_message "$(gettext "The archive will be approximately %d.%02d%s.")" $intnum $fracnum $unit
}
################################################################
# Function gen_ident_and_cookie outputs the cookie and the
# identification lines in the output archive. Also outputs any
# user-specified control sections.
################################################################
gen_ident_and_cookie()
{
typeset keyword
typeset section
typeset bad_start
typeset cookie="FlAsH-aRcHiVe-1.0"
typeset ident_begin="section_begin=identification"
typeset hash_key="archive_id="
typeset hash="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
hash_length=${#hash}
hash_offset=`expr ${#cookie} + 1 + ${#ident_begin} + 1 + ${#hash_key}`
hash_file=/tmp/.flarcreate.hash.$$
${CAT} <<-EOF
$cookie
$ident_begin
EOF
if [[ $generate_hash = $YES ]] ; then
if [ -z "${COMPUTEHASH}" ] ; then
print_message "$(gettext "WARNING: computehash not found; cannot generate checksums")"
generate_hash=$NO
else
${COMPUTEHASH} -n
if [ $? != 0 ] ; then
print_message "$(gettext "WARNING: Hash generation only supported on Solaris 8 and later")"
generate_hash=$NO
else
echo "${hash_key}${hash}"
fi
fi
fi
if [[ $root_directory = "/" ]]; then
creation_node=`uname -n`
creation_hardware_class=`uname -m`
creation_platform=`uname -i`
creation_processor=`uname -p`
creation_release=`uname -r`
creation_os_name=`uname -s`
creation_os_version=`uname -v`
else
creation_node=`${CAT} ${root_directory}/etc/nodename`
if [[ "X$creation_node" = "X" ]]; then
creation_node="unknown"
fi
creation_hardware_class="unknown"
creation_platform="unknown"
creation_processor="unknown"
creation_os_version="unknown"
. ${root_directory}/var/sadm/system/admin/INST_RELEASE
case $OS in
Solaris )
creation_os_name=SunOS
case $VERSION in
2.* ) creation_release=5.${$VERSION#*.} ;;
7 ) creation_release=5.7 ;;
8 ) creation_release=5.8 ;;
9 ) creation_release=5.9 ;;
* ) creation_release=unknown ;;
esac
;;
* )
creation_os_name=unknown
creation_release=unknown
;;
esac
fi
${CAT} <<-EOF
files_archived_method=cpio
creation_date=$creation_date
creation_master=$creation_master
content_name=$content_name
creation_node=$creation_node
creation_hardware_class=$creation_hardware_class
creation_platform=$creation_platform
creation_processor=$creation_processor
creation_release=$creation_release
creation_os_name=$creation_os_name
creation_os_version=$creation_os_version
EOF
if [[ $compress_action = $YES ]]; then
echo "files_compressed_method=compress"
else
echo "files_compressed_method=none"
fi
if [[ $sizing_action = $YES ]]; then
echo "files_archived_size=$archive_size"
fi
#### TODO : files_unarchived_size
if [[ ! -z $content_description ]]; then
echo "content_description=$content_description"
fi
if [[ ! -z $content_type ]]; then
echo "content_type=$content_type"
fi
if [[ ! -z $content_author ]]; then
echo "content_author=$content_author"
fi
echo "content_architectures=$(get_platforms)"
for keyword in $new_keywords; do
if [[ $keyword = "${keyword#X-}" ]]; then
print_message "$(gettext "Added keyword %s does not begin with %s.")" $keyword "X-"
fi
echo $keyword
done
echo "section_end=identification"
# Write user-specified sections, if any
for section in $section_list; do
echo "section_begin=$section"
${CAT} $use_directory/$section
echo "section_end=$section"
done
}
#####################################################
# Function gen_archive files performs pipeline of
# cpio and perhaps compress, and perhaps computehash.
#####################################################
gen_archive_files()
{
echo "section_begin=archive"
cd $root_directory
typeset gen_cmd="/usr/lib/flash/fdo filter_dir $FILTER $root_directory | \
${CPIO} -oc"
if [[ $generate_hash = $YES ]] ; then
gen_cmd="$gen_cmd | ${COMPUTEHASH} -f $hash_file"
fi
if [[ $compress_action = $YES ]] ; then
gen_cmd="$gen_cmd | compress -c"
fi
eval ${gen_cmd}
if [[ $? -eq 0 ]]; then
return 0
else
return 1
fi
}
#######################################################
# Function gen_archive performs the high-level control
# of flarcreate.
#######################################################
gen_archive()
{
gen_ident_and_cookie
gen_archive_files
status=$?
if [[ $status != 0 ]] ; then
print_message "$(gettext "Unable to write archive file.")"
return $status
fi
}
#####################################
# Check that user is root
# (/usr/sbin/patchadd validate_uid())
#####################################
typeset -i uid
uid=$(${ID} | ${SED} 's/uid=\([0-9]*\)(.*/\1/')
if (( uid != 0 ))
then
print_error_and_exit "$(gettext "You must be root to execute this script.")"
fi
#########################################################
# Miscellaneous intializations and beginning-of-job steps
#########################################################
current_dir=$(pwd)
NO="No"
YES="Yes"
# make sure required binaries exist
find_utils_or_exit
if [[ $# -lt 3 ]]; then
print_usage_and_exit
fi
####################################################
# Initialize defaults and parse the invoking command
####################################################
content_author=
compress_action=$NO
creation_date=$(date -u '+''%Y''%m''%d''%H''%M''%S')
content_description_path=
use_directory=$PWD
creation_master=$(${UNAME} -n)
content_name=
tape_position=
tape_blocksize=
file_list=
exclusive_file_list=$NO
tape_block_default="64k"
sizing_action=$YES
generate_hash=$YES
hash_offset=0
hash_length=0
hash_file=
section_list=
new_keywords=
tape_usage=$NO
exclude_path=
content_description=
root_directory="/"
old_root_directory="NON_DIFFERENTIAL"
content_type=
archive_outfile=
getopt_error=$NO
DEBUG=0
QUIET=$YES
COMPUTEHASH=
comparsion=new_dir_compare
FILTER="/tmp/flash_filter_one_.$$"
while getopts ":a:b:cCd:e:E:f:FHi:m:n:p:qR:StT:u:U:vx:X:y:z:" opt; do
case $opt in
a ) content_author=$OPTARG ;;
b ) tape_blocksize=$OPTARG ;;
c ) compress_action=$YES ;;
C ) comparsion=full_new_dir_compare ;;
d ) use_directory=$OPTARG ;;
e ) content_description=$OPTARG ;;
E ) content_description_path=$OPTARG ;;
f ) /usr/lib/flash/fdo do_file_list $OPTARG >> $FILTER ;;
F ) echo - / >> $FILTER ;;
i ) creation_date=$OPTARG ;;
m ) creation_master=$OPTARG ;;
n ) content_name=$OPTARG ;;
H ) generate_hash=$NO ;;
p ) tape_position=$OPTARG ;;
q ) QUIET=$YES ;; # PRIVATE
R ) root_directory=$OPTARG ;;
S ) sizing_action=$NO ;;
t ) tape_usage=$YES ;;
T ) content_type=$OPTARG ;;
u ) section_list="$section_list $OPTARG" ;;
U ) new_keywords="$new_keywords $OPTARG" ;;
v ) DEBUG=1 ;; # PRIVATE
x ) echo - $OPTARG >> $FILTER ;;
X ) /usr/lib/flash/fdo do_x_list $OPTARG >> $FILTER ;;
y ) echo + $OPTARG >> $FILTER ;;
z ) cat $OPTARG >> $FILTER ;;
\? ) print_error_and_usage "$(gettext "Option -%s is invalid.")" $OPTARG ;;
\: ) print_error_and_usage "$(gettext "Option -%s has no value.")" $OPTARG ;;
* ) print usage and exit ;;
esac
done
# find a valid computehash
if [ -x /usr/sbin/computehash ] ; then
COMPUTEHASH=/usr/sbin/computehash
elif [ -x `dirname $0`/computehash ] ; then
_pwd=$PWD
cd `dirname $0`
COMPUTEHASH=`pwd`/computehash
cd $_pwd
else
COMPUTEHASH=
fi
# Isolate outfile parameter - it should be the only argument left
shift $(($OPTIND - 1))
if [[ $# != 1 ]] ; then
print_usage_and_exit
fi
archive_outfile=$1
###############################################
# Make format, dependency, and existence checks
###############################################
if [[ ! -d $root_directory ]] ; then
print_error_and_usage "$(gettext "Directory %s does not exist or is not a directory.")" $root_directory
fi
if [[ $root_directory = ${root_directory#/} ]]; then
print_error_and_usage "$(gettext "Root directory must have an absolute path.")"
fi
#on_local_fs $root_directory
#if [[ $? != 0 ]] ; then
# print_error_and_exit "$(gettext "Root directory must be on a ufs or vxfs file system.")"
#fi
if [[ -z $content_name ]]; then
print_error_and_usage "$(gettext 'Content name (option -n) must have a value.')"
fi
if [[ ${#creation_date} -ne 14 ]]; then
print_error_and_usage "$(gettext "Creation date %s must be 14 digits long.")" $creation_date
fi
if [[ $creation_date != +([0-9]) ]]; then
print_error_and_usage "$(gettext "Creation date %s must be numeric.")" $creation_date
fi
if [[ ! -z $content_description_path ]]; then
if [[ ! -z $content_description ]]; then
print_error_and_usage "$(gettext "Options -E and -e are mutually exclusive.")"
fi
if [[ ! -r $content_description_path ]]; then
print_error_and_exit "$(gettext "Content description file %s is not available.")" $content_description_path
fi
content_description=$(< $content_description_path)
fi
if [[ $use_directory != $PWD && -z $section_list ]]; then
print_error_and_usage "$(gettext "Option -d is invalid in the absence of option -u.")"
fi
for section in $section_list; do
if [[ ! -r $use_directory/$section ]]; then
print_error_and_exit "$(gettext "User section %s is not available.")" $use_directory/$section
fi
done
if [[ ! -z $tape_position ]]; then
if [[ $tape_usage = $NO ]]; then
print_error_and_usage "$(gettext "Option -p is invalid in the absence of option -t.")"
else
# $tape_usage = $YES
if [[ $tape_position != +([0-9]) ]]; then
print_error_and_exit "$(gettext "Tape position %s must be a number.")" $tape_position
fi
fi
fi
if [[ ! -z $tape_blocksize && $tape_usage = $NO ]]; then
print_error_and_usage "$(gettext "Option -b is invalid in the absence of option -t.")"
fi
if [[ $tape_usage = $YES ]]; then
tape_blocksize=${tape_blocksize:-$tape_block_default}
if [[ $tape_blocksize != +([0-9])?(@(k|b|w)) ]]; then
print_error_and_exit "$(gettext "Tape blocksize %s must be number[k|b|w].")" $tape_blocksize
fi
if [[ $generate_hash = $YES ]]; then
print_message "$(gettext 'WARNING: hash generation disabled when using tape (-t)')"
generate_hash=$NO
fi
fi
if [[ ! -z $exclude_path ]]; then
if [[ ! -z "$root_directory" ]] ; then
# make exclude dir relative to alternate root
exclude_path=$root_directory/${exclude_path#/}
fi
if [[ ! -d $exclude_path ]]; then
print_error_and_exit "$(gettext "Exclusion path %s is not a directory.")" $exclude_path
else
# Make relative exclude path absolute. If we have an exclude
# path AND an alternate root, this will never happen, as the
# resulting exclude path will always be absolute after prepending
# the alternate root.
if [[ $exclude_path = ${exclude_path#/} ]]; then
exclude_path=$(pwd)/$exclude_path
fi
fi
# collapse multiple /'s into a single /
exclude_path=`echo $exclude_path | tr -s /`
[[ $DEBUG -ge 1 ]] && echo "Using exclude path: $exclude_path"
exclude_inode=$(${LS} -id $exclude_path |${AWK} '{print $1}')
fi
if [[ -z $archive_outfile ]]; then
if [[ $tape_usage = $NO ]]; then
print_error_and_usage "$(gettext "Path name for new archive must be provided.")"
else
print_error_and_usage "$(gettext "Tape drive name for new archive must be provided.")"
fi
fi
if [[ $tape_usage = $NO ]]; then
if [[ $archive_outfile = ${archive_outfile#/} ]]; then
archive_outfile=$(pwd)/$archive_outfile
fi
if [[ -e $archive_outfile ]]; then
${RM} -f $archive_outfile
fi
${TOUCH} $archive_outfile
if [[ ! -w $archive_outfile ]]; then
print_error_and_exit "$(gettext "Archive file %s is not writable.")" $archive_outfile
fi
read archive_inode junk <<-EOF
$(${LS} -i $archive_outfile)
EOF
fi
# append current directory if filelist is relative
if [[ -n "$file_list" ]] ; then
if [[ $file_list = ${file_list#/} ]]; then
file_list=$(pwd)/$file_list
fi
fi
# we can't size the archive when doing a streamed file list, since
# we can only read the file list once.
if [[ "$file_list" = "-" && $sizing_action = $YES ]] ; then
print_message "$(gettext "WARNING: Sizing not supported when using streamed file list")"
sizing_action=$NO
fi
##############################################
# Determine what filesystems to archive, and
# build the archive pipelines
##############################################
start_dial
echo - /${archive_outfile#${root_directory}} >> $FILTER
(${CAT} /etc/vfstab;echo mnttab;${CAT} /etc/mnttab) | /usr/lib/flash/fdo mountpoints_to_filter ${root_directory} >> $FILTER
echo ". /cdrom" >> $FILTER
echo ". /floppy" >> $FILTER
#/usr/lib/flash/fdo contents_to_filter /var/sadm/install/contents >> $FILTER
/usr/lib/flash/fdo sort_list $root_directory $FILTER > /tmp/flash_filter_two_.$$
${RM} -f $FILTER
FILTER="/tmp/flash_filter_two_.$$"
echo current filter settings
#echo integrity check
#/usr/lib/flash/fdo integrity_check $FILTER /var/sadm/install/contents
# Exclude the archive file if we're not using tape and the archive
# file is on this filesystem
# If we're using an exclude path and it's on this filesystem,
# exclude it
stop_dial
##########################################
# If asked, find out size of archive-to-be
##########################################
if [[ $sizing_action = $YES ]]; then
size_archive
fi
######################################
# Position magnetic tape, if requested
######################################
if [[ $tape_usage = $YES && ! -z $tape_position ]]; then
print_message "$(gettext "Positioning tape drive...")"
start_dial
${MT} -f $archive_outfile asf $tape_position
if [[ $? -gt 0 ]]; then
print_error_and_exit "$(gettext "Unable to move tape %s to position %d.")" $archive_outfile $tape_position
fi
stop_dial
fi
###################
# Write the archive
###################
print_message "$(gettext "Creating the archive...")"
start_dial
# Use output redirection for disk, dd for tape
if [[ $tape_usage = $NO ]]; then
gen_archive > $archive_outfile
${MT} -f $archive_outfile asf $tape_position
if [[ $? -gt 0 ]]; then
print_error_and_exit "$(gettext "Unable to move tape %s to position %d.")" $archive_outfile $tape_position
fi
stop_dial
fi
###################
# Write the archive
###################
print_message "$(gettext "Creating the archive...")"
start_dial
# Use output redirection for disk, dd for tape
if [[ $tape_usage = $NO ]]; then
gen_archive > $archive_outfile
else
gen_archive | ${DD} of=$archive_outfile obs=$tape_blocksize 2>/dev/null
fi
status=$?
# add hash, if we computed one. lets hope the hash goes near the
# beginning of the file or the seek will take forever with a blocksize of 1.
if [[ $generate_hash = $YES ]] ; then
if [ -r $hash_file -a -f $hash_file ] ; then
${DD} if=$hash_file of=$archive_outfile bs=1 count=$hash_length \
seek=$hash_offset conv=notrunc >/dev/null 2>&1
${RM} -f $hash_file
else
print_error_and_exit "$(gettext "Could not generate hash for %s")" $archive_outfile
fi
fi
stop_dial
if [[ $status != 0 ]] ; then
print_error_and_exit "$(gettext "Unable to work archive.")"
fi
#########################################
# Perform end-of-job processing, and exit
#########################################
${RM} $FILTER
print_message "$(gettext "Archive creation complete.")"
exit 0
anything missing?
run find_utils.sh below
cp the binaries to the locations
if in doubt run ldd -f ./binary
fdo requires a directory:
bash-2.03# mkdir /usr/lib/flash/
bash-2.03# cp /tmp/flar_archive/fdo /usr/lib/flash/
find_utils.sh
#!/bin/ksh
# list of required utilities. If you add any to this
# list, be sure to also add it to the $UTIL_LIST variable below!
AWK="/usr/bin/awk"
RM="/usr/bin/rm"
CPIO="/usr/bin/cpio"
COMPRESS="/usr/bin/compress"
UNCOMPRESS="/usr/bin/uncompress"
CAT="/usr/bin/cat"
ZCAT="/usr/bin/zcat"
FIND="/usr/bin/find"
TOUCH="/usr/bin/touch"
MT="/usr/bin/mt"
DD="/usr/bin/dd"
MKDIR="/usr/bin/mkdir"
FLAR="/usr/sbin/flar"
FLARCREATE="/usr/sbin/flarcreate"
COMPUTEHASH="/usr/sbin/computehash"
BPGETFILE="/usr/sbin/bpgetfile"
FDOLIB="/usr/lib/flash/fdo"
UTIL_LIST="$AWK $RM $CPIO $COMPRESS $UNCOMPRESS $CAT $ZCAT $FIND $TOUCH $MT $DD $MKDIR $FLAR $FLARCREATE $COMPUTEHASH $BPGETFILE $FDOLIB"
##############################################################
# find binaries required to flarcreate.
##############################################################
{
for i in $UTIL_LIST ; do
if [ ! -x $i ] ; then
"$(gettext "Required utility $i is not available.")" $i
fi
done
}
exit 0
Tuesday, May 12, 2015
flarcreate for solaris backups
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment