diff --git a/beadm b/beadm index 5a32cd4..9df9bdf 100755 --- a/beadm +++ b/beadm @@ -43,7 +43,7 @@ __usage() { echo " ${NAME} create [-e nonActiveBe | -e beName@snapshot] beName" echo " ${NAME} create beName@snapshot" echo " ${NAME} destroy [-F] beName | beName@snapshot" - echo " ${NAME} list" + echo " ${NAME} list [-S]" echo " ${NAME} mount" echo " ${NAME} mount beName [mountpoint]" echo " ${NAME} umount | unmount [-f] beName" @@ -51,7 +51,7 @@ __usage() { exit 1 } -# check if BE exists +# check if boot environment exists __be_exist() { # 1=DATASET if ! zfs list -H -o name ${1} 1> /dev/null 2> /dev/null then @@ -65,7 +65,7 @@ __be_snapshot() { # 1=DATASET/SNAPSHOT echo "${1}" | grep -q "@" } -# create new BE +# create new boot environment __be_new() { # 1=SOURCE 2=TARGET local SOURCE=$( echo ${1} | cut -d '@' -f 1 ) if __be_snapshot ${1} @@ -86,12 +86,12 @@ __be_new() { # 1=SOURCE 2=TARGET echo "ERROR: Snapshot '${1}@${2##*/}' already exists" exit 1 fi -### if ! zfs snapshot -r ${1}@${2##*/} 1> /dev/null 2> /dev/null # old # FMT=$( date "+%Y-%m-%d-%H:%M:%S" ) # NEW # if ! zfs snapshot -r ${1}@${FMT} 1> /dev/null 2> /dev/null # NEW # + # if ! zfs snapshot -r ${1}@${2##*/} 1> /dev/null 2> /dev/null # old # then -##### echo "ERROR: Cannot create snapshot '${1}@${2##*/}'" # old # echo "ERROR: Cannot create snapshot '${1}@${FMT}'" # NEW # + # echo "ERROR: Cannot create snapshot '${1}@${2##*/}'" # old # exit 1 fi fi @@ -103,7 +103,7 @@ __be_new() { # 1=SOURCE 2=TARGET do local OPTS="-o ${PROPERTY}=${VALUE} ${OPTS}" done << EOF -$( zfs get -o name,property,value -s local,received -H all ${FS} | grep -v -E "(canmount)" ) +$( zfs get -o name,property,value -s local,received -H all ${FS} | grep -v -E "canmount" ) EOF DATASET=$( echo ${FS} | awk '{print $1}' | sed -E s/"^${POOL}\/ROOT\/${SOURCE##*/}"/"${POOL}\/ROOT\/${2##*/}"/g ) if [ "${OPTS}" = "-o = " ] @@ -114,7 +114,7 @@ EOF then zfs clone -o canmount=off ${OPTS} ${FS}@${1##*@} ${DATASET} else -######### zfs clone -o canmount=off ${OPTS} ${FS}@${2##*/} ${DATASET} # old # + # zfs clone -o canmount=off ${OPTS} ${FS}@${2##*/} ${DATASET} # old # zfs clone -o canmount=off ${OPTS} ${FS}@${FMT} ${DATASET} # NEW # fi done @@ -123,7 +123,7 @@ EOF ROOTFS=$( mount | awk '/ \/ / {print $1}' ) -if echo ${ROOTFS} | grep -q -E "^/dev/" +if echo ${ROOTFS} | grep -q -m 1 -E "^/dev/" then echo "ERROR: This system does not boot from ZFS pool" exit 1 @@ -142,23 +142,23 @@ BOOTFS=$( zpool list -H -o bootfs ${POOL} ) case ${1} in (list) # -------------------------------------------------------------------- - if [ ${#} -ne 1 ] + if [ ${#} -ne 1 -a "${2}" != "-S" ] then __usage fi BENAME_STARTS_WITH="${POOL}/ROOT" - LIST=$( zfs list -o name,mountpoint,creation -s creation -H -d 1 -r ${POOL}/ROOT | grep -E "^${POOL}/ROOT/" ) + LIST=$( zfs list -o name,used,mountpoint,creation -s creation -H -d 1 -r ${POOL}/ROOT | grep -E "^${POOL}/ROOT/" ) WIDTH_CREATION=$( echo "${LIST}" | awk '{print $5}' | wc -L ) WIDTH_NAME=$( echo "${LIST}" | awk '{print $1}' | wc -L ) WIDTH_NAME=$(( ${WIDTH_NAME} - ${#BENAME_STARTS_WITH} - 1 )) printf "%-${WIDTH_NAME}s %-6s %-10s %6s %6s %s\n" \ BE Active Mountpoint Space Policy Created echo "${LIST}" \ - | while read NAME MOUNTPOINT Y m d H M + | while read NAME USED MOUNTPOINT Y m d H M do TOTAL=0 NAME=${NAME##*/} - unset ACTIVE + ACTIVE='' if [ "${BENAME_STARTS_WITH}/${NAME}" = "${ROOTFS}" ] then ACTIVE="${ACTIVE}N" @@ -171,76 +171,50 @@ case ${1} in then ACTIVE="-" fi - printf "%-${WIDTH_NAME}s %-6s " ${NAME} ${ACTIVE} case ${ACTIVE} in (N|NR) MOUNT="/" ;; (*) MOUNT="-" ;; esac - while read I - do - USED=$( zfs list -H -o used ${I} ) - if [ ${USED} = "0" ] - then - continue - fi - case "${USED}" in - (*K) SIZE=$( echo "${USED} * 1000 " | tr -c -d '\[0-9]* .\n' | bc -l ) ;; - (*M) SIZE=$( echo "${USED} * 1000000 " | tr -c -d '\[0-9]* .\n' | bc -l ) ;; - (*G) SIZE=$( echo "${USED} * 1000000000 " | tr -c -d '\[0-9]* .\n' | bc -l ) ;; - (*T) SIZE=$( echo "${USED} * 1000000000000 " | tr -c -d '\[0-9]* .\n' | bc -l ) ;; - (*P) SIZE=$( echo "${USED} * 1000000000000000 " | tr -c -d '\[0-9]* .\n' | bc -l ) ;; - (*E) SIZE=$( echo "${USED} * 1000000000000000000 " | tr -c -d '\[0-9]* .\n' | bc -l ) ;; - (*Z) SIZE=$( echo "${USED} * 1000000000000000000000" | tr -c -d '\[0-9]* .\n' | bc -l ) ;; - (*) SIZE="${USED}" ;; - esac - TOTAL=$( echo "${SIZE} + ${TOTAL}" | bc -l ) - done << EOF -$( zfs list -H -t all -o name,origin -r "${BENAME_STARTS_WITH}/${NAME}" | tr '\t' '\n' | grep -v -E "^-$" ) + if [ "${2}" = "-S" ] + then + USED_ALL=$( zfs list -H -t all -o name,used ) + while read I + do + USED=$( echo "${USED_ALL}" | grep -m 1 -E "^${I}" | awk '{print $2}' ) + if [ ${USED} = "0" ] + then + continue + fi + case "${USED}" in + (*K) USED=$( echo "${USED} * 10" | sed s/K// | bc | cut -d '.' -f 1 ); USED=$(( ${USED} * 100 )) ;; + (*M) USED=$( echo "${USED} * 10" | sed s/M// | bc | cut -d '.' -f 1 ); USED=$(( ${USED} * 100000 )) ;; + (*G) USED=$( echo "${USED} * 10" | sed s/G// | bc | cut -d '.' -f 1 ); USED=$(( ${USED} * 100000000 )) ;; + (*T) USED=$( echo "${USED} * 10" | sed s/T// | bc | cut -d '.' -f 1 ); USED=$(( ${USED} * 100000000000 )) ;; + (*P) USED=$( echo "${USED} * 10" | sed s/P// | bc | cut -d '.' -f 1 ); USED=$(( ${USED} * 100000000000000 )) ;; + (*E) USED=$( echo "${USED} * 10" | sed s/E// | bc | cut -d '.' -f 1 ); USED=$(( ${USED} * 100000000000000000 )) ;; + # 100000000000000000 is maximum that is supported by $(( )) + (*Z) USED=$( echo "${USED} * 10000000000000000000" | sed s/Z// | bc ) ;; + esac + TOTAL=$(( $( echo ${USED} | cut -d '.' -f 1 ) + ${TOTAL} )) + done << EOF +$( zfs list -H -t all -o name,origin -r "${BENAME_STARTS_WITH}/${NAME}" | tr '\t' '\n' | grep -v "^-$" ) EOF - RANGE=$( echo ${TOTAL} | cut -d . -f 1 ) - case $( echo "${RANGE}" | wc -c | tr -c -d '[0-9]\n' ) in - (5|6|7) TOTAL="$( echo ${TOTAL} / 1000 | bc -l | grep -o -E "[0-9]*\.[0-9]{1}" )K" ;; - (8|9|10) TOTAL="$( echo ${TOTAL} / 1000000 | bc -l | grep -o -E "[0-9]*\.[0-9]{1}" )M" ;; - (11|12|13) TOTAL="$( echo ${TOTAL} / 1000000000 | bc -l | grep -o -E "[0-9]*\.[0-9]{1}" )G" ;; - (14|15|16) TOTAL="$( echo ${TOTAL} / 1000000000000 | bc -l | grep -o -E "[0-9]*\.[0-9]{1}" )T" ;; - (17|18|19) TOTAL="$( echo ${TOTAL} / 1000000000000000 | bc -l | grep -o -E "[0-9]*\.[0-9]{1}" )P" ;; - (20|21|22) TOTAL="$( echo ${TOTAL} / 1000000000000000000 | bc -l | grep -o -E "[0-9]*\.[0-9]{1}" )E" ;; - (23|24|25) TOTAL="$( echo ${TOTAL} / 1000000000000000000000 | bc -l | grep -o -E "[0-9]*\.[0-9]{1}" )Z" ;; - esac - printf "%-10s %6s %-6s " ${MOUNT} ${TOTAL} "static" + RANGE=$( echo ${TOTAL} | cut -d . -f 1 ) + case $( echo "${RANGE}" | wc -c | tr -c -d '[0-9]\n' ) in + (5|6|7) TOTAL="$( echo ${TOTAL} / 1000 | bc -l | grep -m 1 -o -E "[0-9]*\.[0-9]{1}" )K" ;; + (8|9|10) TOTAL="$( echo ${TOTAL} / 1000000 | bc -l | grep -m 1 -o -E "[0-9]*\.[0-9]{1}" )M" ;; + (11|12|13) TOTAL="$( echo ${TOTAL} / 1000000000 | bc -l | grep -m 1 -o -E "[0-9]*\.[0-9]{1}" )G" ;; + (14|15|16) TOTAL="$( echo ${TOTAL} / 1000000000000 | bc -l | grep -m 1 -o -E "[0-9]*\.[0-9]{1}" )T" ;; + (17|18|19) TOTAL="$( echo ${TOTAL} / 1000000000000000 | bc -l | grep -m 1 -o -E "[0-9]*\.[0-9]{1}" )P" ;; + (20|21|22) TOTAL="$( echo ${TOTAL} / 1000000000000000000 | bc -l | grep -m 1 -o -E "[0-9]*\.[0-9]{1}" )E" ;; + (23|24|25) TOTAL="$( echo ${TOTAL} / 1000000000000000000000 | bc -l | grep -m 1 -o -E "[0-9]*\.[0-9]{1}" )Z" ;; + esac + else + TOTAL=${USED} + fi + printf "%-${WIDTH_NAME}s %-6s %-10s %6s %-6s " ${NAME} ${ACTIVE} ${MOUNT} ${TOTAL} "static" date -j -f "%a %b %d %H:%M %Y" "${Y} ${m} ${d} ${H} ${M}" +"%Y-%m-%d %H:%M" done -####### LIST=$( zfs list -o name,used,mountpoint,creation -s creation -H -d 1 -r ${POOL}/ROOT | grep -E "^${POOL}/ROOT/" ) -####### WIDTH_CREATION=$( echo "${LIST}" | awk '{print $5}' | wc -L ) -####### WIDTH_NAME=$( echo "${LIST}" | awk '{print $1}' | wc -L ) -####### WIDTH_NAME=$(( ${WIDTH_NAME} - ${#BENAME_STARTS_WITH} - 1 )) -####### printf "%-${WIDTH_NAME}s %-6s %-10s %5s %6s %s\n" \ -####### BE Active Mountpoint Space Policy Created -####### echo "${LIST}" \ -####### | while read NAME USED MOUNTPOINT Y m d H M -####### do -####### NAME=${NAME##*/} -####### unset ACTIVE -####### if [ "${BENAME_STARTS_WITH}/${NAME}" = "${ROOTFS}" ] -####### then -####### ACTIVE="${ACTIVE}N" -####### fi -####### if [ "${BENAME_STARTS_WITH}/${NAME}" = "${BOOTFS}" ] -####### then -####### ACTIVE="${ACTIVE}R" -####### fi -####### if [ -z "${ACTIVE}" ] -####### then -####### ACTIVE="-" -####### fi -####### printf "%-${WIDTH_NAME}s %-6s " ${NAME} ${ACTIVE} -####### case ${ACTIVE} in -####### (N|NR) MOUNT="/" ;; -####### (*) MOUNT="-" ;; -####### esac -####### printf "%-10s %5s %-6s " ${MOUNT} ${USED} "static" -####### date -j -f "%a %b %d %H:%M %Y" "${Y} ${m} ${d} ${H} ${M}" +"%Y-%m-%d %H:%M" -####### done ;; (create) # ------------------------------------------------------------------ @@ -411,58 +385,15 @@ EOF fi done # get origins used by destroyed boot environment - ORIGINS=$( zfs list -H -t all -o origin -r ${POOL}/ROOT/${DESTROY} ) + ORIGINS=$( zfs list -H -t all -o origin -r ${POOL}/ROOT/${DESTROY} | grep -v '^-$' ) # destroy boot environment zfs destroy -r ${POOL}/ROOT/${DESTROY} # destroy origins used by destroyed boot environment echo "${ORIGINS}" \ | while read I do - if [ "${I}" != "-" ] - then - zfs destroy ${I} - fi + zfs destroy ${I} done -############## # destroy desired boot environment -############## zfs list -r -H -o name ${POOL}/ROOT/${DESTROY} \ -############## | sort -n -r \ -############## | while read DATASET -############## do -############## zfs umount ${DATASET} 1> /dev/null 2> /dev/null || true -############## done -############## # get origins that needs to be deleted -############## ORIGINS=$( zfs list -r -H -o origin ${POOL}/ROOT/${DESTROY} ) -############## # promote dependent clones -############## zfs list -H -o name,origin \ -############## | awk -v destroy=${POOL}/ROOT/${DESTROY} '$2 ~ destroy {print $1}' \ -############## | sort -r \ -############## | while read I -############## do -############## echo PROMOTE 1: $I -############## zfs promote ${I} 2> /dev/null -############## done -############## # destroy desired boot environment -############## if ! zfs destroy ${POOL}/ROOT/${DESTROY} 1> /dev/null 2> /dev/null -############## then -############## # promote dependent clones when needed -############## zfs destroy -r ${POOL}/ROOT/${DESTROY} 2>&1 \ -############## | grep "${POOL}/ROOT/" \ -############## | grep -v "@" \ -############## | while read I -############## do -############## echo PROMOTE 2: $I -############## zfs promote ${I} 2> /dev/null -############## done -############## fi -############## # destroy origins that needs to be deleted -############## if [ "${ORIGINS}" != "-" ] -############## then -############## echo "${ORIGINS}" \ -############## | while read I -############## do -############## zfs destroy -r ${I} 2> /dev/null || true -############## done -############## fi fi echo "Destroyed successfully" ;;