diff --git a/beadm b/beadm index aa8f8f9..a0b0074 100755 --- a/beadm +++ b/beadm @@ -172,208 +172,167 @@ fi case ${1} in (list) # -------------------------------------------------------------------- - if [ ${#} -ne 1 -a "${2}" != "-a" -a "${2}" != "-D" ] + OPTION_a=0 + OPTION_D=0 + shift + while getopts "aD" OPT + do + case ${OPT} in + (a) OPTION_a=1 ;; + (D) OPTION_D=1 ;; + (*) __usage ;; + esac + done + if [ ${OPTION_a} -eq 1 -a ${OPTION_D} -eq 1 ] then __usage fi - if [ "${2}" = "-D" ] - then - awk -v pool="${POOL}" -v rootfs="${ROOTFS}" -v bootfs="${BOOTFS}" \ - 'function normalize(v) { - return substr(v, 1, length(v) - 1) * multiplier[substr(v, length(v))] - } - function show_units(v) { - if(v <= 1024) { unit = "K"; } - else if(v <= 1048576) { v = v / 1024; unit = "M"; } - else if(v <= 1073741824) { v = v / 1048576; unit = "G"; } - else if(v <= 1099511627776) { v = v / 1073741824; unit = "T"; } - else if(v <= 1125899906842624) { v = v / 1099511627776; unit = "P"; } - else if(v <= 1152921504606846976) { v = v / 1125899906842624; unit = "E"; } - else { v = v / 1152921504606846976; unit = "Z"; } - fmt = "%.1f" - return sprintf(fmt "%s", v, unit) - } - function get_bename(v) { - sub(bename_begins_with "\/", "", v) - sub("/.*", "", v) - return v - } - BEGIN { - FS = "\\t" - bename_begins_with = pool "/ROOT" - multiplier["K"] = 1 - multiplier["M"] = 1024 - multiplier["G"] = 1048576 - multiplier["T"] = 1073741824 - multiplier["P"] = 1099511627776 - multiplier["E"] = 1125899906842624 - multiplier["Z"] = 1152921504606846976 - mountpoint_length = 10 - while("zfs list -H -o name,usedds,usedbysnapshots,usedrefreserv,refer,origin -r " bename_begins_with | getline) { - bename = get_bename($1) - if(! (bename in size)) { - l = length(bename) - if(l > bename_length) bename_length = l - mountpoint = "-" - mountline = "" - "mount | grep \"^" $1 " \"" | getline mountline - split(mountline, mountdata, " ") - mountpoint = mountdata[3] - mount[bename] = mountpoint - l = length(mountpoint) - if(l > mountpoint_length) mountpoint_length = l - } - if($6 == "-") size[bename] += (normalize($2) + normalize($4)) - else size[bename] += (normalize($2) + normalize($4) + normalize($5)) + awk -v POOL="${POOL}" \ + -v ROOTFS="${ROOTFS}" \ + -v BOOTFS="${BOOTFS}" \ + -v OPTION_a="${OPTION_a}" \ + -v OPTION_D="${OPTION_D}" \ + 'function __normalize(VALUE) { + return substr(VALUE, 1, length(VALUE) - 1) * MULTIPLIER[substr(VALUE, length(VALUE))] + } + function __show_units(VALUE) { + if(VALUE < 1025) { UNIT = "K"; } + else if(VALUE < 1048576) { VALUE /= 1024; UNIT = "M"; } + else if(VALUE < 1073741824) { VALUE /= 1048576; UNIT = "G"; } + else if(VALUE < 1099511627776) { VALUE /= 1073741824; UNIT = "T"; } + else if(VALUE < 1125899906842624) { VALUE /= 1099511627776; UNIT = "P"; } + else if(VALUE < 1152921504606846976) { VALUE /= 1125899906842624; UNIT = "E"; } + else { VALUE /= 1152921504606846976; UNIT = "Z"; } + return sprintf("%.1f%s", VALUE, UNIT) + } + function __get_bename(BENAME) { + sub(BENAME_BEGINS_WITH "\/", "", BENAME) + sub("/.*", "", BENAME) + return BENAME + } + function __convert_date(DATE) { + "date -j -f \"%a %b %d %H:%M %Y\" \"" DATE "\" +\"%Y-%m-%d %H:%M\"" | getline NEW + close("date -j -f \"%a %b %d %H:%M %Y\" \"" DATE "\" +\"%Y-%m-%d %H:%M\"") + return NEW + } + BEGIN { + FS = "\\t" + BENAME_BEGINS_WITH = POOL "/ROOT" + MULTIPLIER["K"] = 1 + MULTIPLIER["M"] = 1024 + MULTIPLIER["G"] = 1048576 + MULTIPLIER["T"] = 1073741824 + MULTIPLIER["P"] = 1099511627776 + MULTIPLIER["E"] = 1125899906842624 + MULTIPLIER["Z"] = 1152921504606846976 + MOUNTPOINT_LENGTH = 10 + FSNAME_LENGTH = 2 + if(OPTION_a == 1) + FSNAME_LENGTH = 19 + while("zfs list -H -t all -s creation -o name,used,usedds,usedbysnapshots,usedrefreserv,refer,creation,origin -r " BENAME_BEGINS_WITH | getline) { + FSNAME = $1 + FSNAMES[length(FSNAMES) + 1] = FSNAME + if(FSNAME != BENAME_BEGINS_WITH) { + if(FSNAME ~ "@") + SPACES[FSNAME] = __normalize($2) + __normalize($5) + else { + SPACES[FSNAME] = __normalize($3) + __normalize($5) + BE = " " __get_bename(FSNAME) " " + if(index(BELIST, BE) == 0) + BELIST = BELIST " " BE + } + USEDBYSNAPSHOTS = $4 + USEDREFRESERV[FSNAME] = __normalize($5) + REFER[FSNAME] = __normalize($6) + CREATIONS[FSNAME] = $7 + ORIGINS[FSNAME] = $8 + if(USEDBYSNAPSHOTS != 0 && USEDBYSNAPSHOTS != "-") + SPACES[FSNAME] += __normalize(USEDBYSNAPSHOTS) + MOUNTLINE = "" + "mount | grep \"^" FSNAME " \"" | getline MOUNTLINE + split(MOUNTLINE, MOUNTDATA, " ") + MOUNTPOINT = MOUNTDATA[3] + if(MOUNTPOINT == "") + MOUNTPOINT = "-" + MOUNTS[FSNAME] = MOUNTPOINT + LM = length(MOUNTPOINT) + if((OPTION_a == 0 && FSNAME == (BENAME_BEGINS_WITH "/" __get_bename(FSNAME))) || (OPTION_a == 1 && FSNAME !~ /@/)) { + if(LM > MOUNTPOINT_LENGTH) + MOUNTPOINT_LENGTH = LM + } + if(OPTION_a == 1) + LF = length(FSNAME) + else if(FSNAME !~ /@/) + LF = length(__get_bename(FSNAME)) + if(LF > FSNAME_LENGTH) + FSNAME_LENGTH = LF } - printf "%-" bename_length "s %-6s %-" mountpoint_length "s %6s %s\n", "BE", "Active", "Mountpoint", "Space", "Created" - while("zfs list -H -o name,mountpoint,creation -s creation -d 1 " bename_begins_with | getline) { - if($1 !~ /ROOT$/) { - active = "" - if($1 == rootfs) active = active "N" - if($1 == bootfs) active = active "R" - if(! active) {active = "-"} - bename = get_bename($1) - sub("^.*/", "", bename) - "date -j -f \"%a %b %d %H:%M %Y\" \"" $3 "\" +\"%Y-%m-%d %H:%M\"" | getline creation - printf "%-" bename_length "s %-6s %-" mountpoint_length "s %6s %-6s\n", bename, active, mount[bename], show_units(size[bename]), creation + } + split(BELIST, BENAMES, " ") + if(OPTION_a == 1) { + BE_HEAD = "BE/Dataset/Snapshot" + FSNAME_LENGTH += 2 + } + else + BE_HEAD = "BE" + printf "%-" FSNAME_LENGTH "s %-6s %-" MOUNTPOINT_LENGTH "s %6s %s\n", BE_HEAD, "Active", "Mountpoint", "Space", "Created" + for(I = 1; I <= length(BENAMES); I++) { + BENAME = BENAMES[I] + if(OPTION_a == 1) { + print BENAME + for(J = 1; J <= length(FSNAMES); J++) { + FSNAME = FSNAMES[J] + if(FSNAME ~ "^" BENAME_BEGINS_WITH "/" BENAME "(/[^@]*)?$") { + ACTIVE = "" + if(FSNAME == ROOTFS) + ACTIVE = ACTIVE "N" + if(FSNAME == BOOTFS) + ACTIVE = ACTIVE "R" + if(! ACTIVE) + ACTIVE = "-" + printf " %-" FSNAME_LENGTH "s %-6s %-" MOUNTPOINT_LENGTH "s %6s %s\n", FSNAME, ACTIVE, MOUNTS[FSNAME], __show_units(SPACES[FSNAME]), __convert_date(CREATIONS[FSNAME]) + ORIGIN = ORIGINS[FSNAME] + if(ORIGIN != "-") { + if(OPTION_D == 1) + SPACE = REFER[ORIGIN] + else + SPACE = SPACES[ORIGIN] + printf " %-" FSNAME_LENGTH "s %-6s %-" MOUNTPOINT_LENGTH "s %6s %s\n", ORIGIN, "-", MOUNTS[ORIGIN], __show_units(SPACE), __convert_date(CREATIONS[ORIGIN]) + } + } } } - }' - exit 0 - fi - if [ "${2}" = "-a" ] - then - ZFS_LIST=$( zfs list -o name,mountpoint,used,creation -H -t all -r ${POOL}/ROOT | sed 1d ) - else - ZFS_LIST=$( zfs list -o name,mountpoint,used,creation -s creation -H -d 1 -r ${POOL}/ROOT | sed 1d ) - fi - WIDTH_CREATION=$( echo "${ZFS_LIST}" | awk '{print $5}' | wc -L ) - WIDTH_NAME=$( echo "${ZFS_LIST}" | awk '{print $1}' | wc -L ) - ZFS_MOUNT_LIST=$( zfs mount | grep "^${POOL}/ROOT/" ) - if [ "${2}" = "-a" ] - then - WIDTH_MOUNT=$( echo "${ZFS_MOUNT_LIST}" | awk '{print $2}' | wc -L ) - else - BENAMES=$( echo "${ZFS_LIST}" | awk '{print $1}' | xargs basename | tr '\n' '|' | sed 's/.$//' ) - WIDTH_MOUNT=$( echo "${ZFS_MOUNT_LIST}" | grep -E "(${BENAMES}) " | awk '{print $2}' | wc -L ) - WIDTH_NAME=$(( ${WIDTH_NAME} - ${#POOL} - 6 )) - if [ ${WIDTH_MOUNT} -lt 10 ] - then - WIDTH_MOUNT=10 - fi - fi - # get list of USEDBYDATASET and USED properties - USED_ALL=$( zfs list -H -t all -o name,usedbydataset,usedbysnapshots,used -r sys/ROOT \ - | sed 1d \ - | sed '/0$/d' \ - | sed '/-$/d' \ - | awk '{ gsub("-"," 0 0 ",$2); gsub("-"," 0 0 ",$3); gsub("-"," 0 0 ",$4); - gsub("K"," 1 ",$2); gsub("K"," 1 ",$3); gsub("K"," 1 ",$4) - gsub("M"," 1024 ",$2); gsub("M"," 1024 ",$3); gsub("M"," 1024 ",$4); - gsub("G"," 1048576 ",$2); gsub("G"," 1048576 ",$3); gsub("G"," 1048576 ",$4); - gsub("T"," 1073741824 ",$2); gsub("T"," 1073741824 ",$3); gsub("T"," 1073741824 ",$4); - gsub("P"," 1099511627776 ",$2); gsub("P"," 1099511627776 ",$3); gsub("P"," 1099511627776 ",$4); - gsub("E"," 1125899906842624 ",$2); gsub("E"," 1125899906842624 ",$3); gsub("E"," 1125899906842624 ",$4); - gsub("Z"," 1152921504606846976 ",$2); gsub("Z"," 1152921504606846976 ",$3); gsub("Z"," 1152921504606846976 ",$4); - print $0; - }' ) - # get the list of names and origins for all boot environments - SNAPSHOT_ALL=$( zfs list -H -t all -o name,origin -d 1 ${POOL}/ROOT ) - if [ "${2}" = "-a" ] - then - printf "%-${WIDTH_NAME}s %-6s %-${WIDTH_MOUNT}s %6s %s\n" \ - BE/Dataset/Snapshot Active Mountpoint Space Created - else - printf "%-${WIDTH_NAME}s %-6s %-${WIDTH_MOUNT}s %6s %s\n" \ - BE Active Mountpoint Space Created - fi - echo "${ZFS_LIST}" \ - | while read NAME MOUNTPOINT USED a b d HM Y - do - TOTAL=0 - DATASET=${NAME} - NAME=${NAME##*/} - ACTIVE='' - if [ "${POOL}/ROOT/${NAME}" = "${ROOTFS}" ] - then - ACTIVE="${ACTIVE}N" - fi - if [ "${POOL}/ROOT/${NAME}" = "${BOOTFS}" ] - then - ACTIVE="${ACTIVE}R" - fi - if [ -z "${ACTIVE}" ] - then - ACTIVE="-" - fi - if [ "${2}" = "-a" ] - then - MOUNT=$( echo "${ZFS_MOUNT_LIST}" | grep -m 1 "^${DATASET}" | awk '{print $2}' ) - else - MOUNT=$( echo "${ZFS_MOUNT_LIST}" | grep -m 1 "^${POOL}/ROOT/${NAME}" | awk '{print $2}' ) - fi - if [ -z "${MOUNT}" ] - then - MOUNT="-" - fi - # get the name of origin snapshot for boot environment - SNAPSHOT=$( echo "${SNAPSHOT_ALL}" | awk "/^${POOL}\/ROOT\/${NAME}\t/" | awk -F '@' '{print $2}' ) - if [ "${2}" = "-a" ] - then - # use the USED field from ZFS LIST - TOTAL=${USED} - else - # calculate overhead space usage for boot environment - OVERHEAD=$( echo "${USED_ALL}" \ - | grep "^${POOL}\/ROOT\/${NAME}" \ - | grep -v "@" \ - | awk \ - 'BEGIN { overhead = 0 } - { overhead += $4 * $5 } - END { print overhead }' ) - # calculate snapshots space usage for boot environment - SNAPS=$( echo "${USED_ALL}" \ - | grep "^${POOL}\/ROOT\/${NAME}" \ - | grep "@" \ - | awk \ - 'BEGIN { snaps = 0 } - { snaps += $6 * $7 } - END { print snaps }' ) - # calculate space usage for boot environment datasets - USED=$( echo "${USED_ALL}" \ - | awk -v name="^${POOL}\/ROOT\/${NAME}" -v snapshot="@${SNAPSHOT}$" \ - 'BEGIN { used = 0 } - ( $1 ~ name ) { used += $2 * $3 } - ( $1 ~ snapshot ) { used += $6 * $7 } - END { print used }' ) - # calculate total space usage for boot environment - TOTAL=$( echo | awk -v used=${USED} -v snaps=${SNAPS} -v overhead=${OVERHEAD} \ - 'BEGIN { total = used + overhead - snaps } - END { - if(total <= 1024) { unit = "K"; } - else if(total <= 1048576) { total = total / 1024; unit = "M"; } - else if(total <= 1073741824) { total = total / 1048576; unit = "G"; } - else if(total <= 1099511627776) { total = total / 1073741824; unit = "T"; } - else if(total <= 1125899906842624) { total = total / 1099511627776; unit = "P"; } - else if(total <= 1152921504606846976) { total = total / 1125899906842624; unit = "E"; } - else { total = total / 1152921504606846976; unit = "Z"; } - printf("%.1f%s", total, unit); - }' ) - fi - if [ "${2}" = "-a" ] - then - if echo "${DATASET}" | grep -v "@" | grep -q "${POOL}/ROOT/${NAME}" 2> /dev/null - then - echo ${NAME} - fi - printf " %-${WIDTH_NAME}s %-6s %-${WIDTH_MOUNT}s %6s " ${DATASET} ${ACTIVE} ${MOUNT} ${TOTAL} - date -j -f "%a %b %d %H:%M %Y" "${a} ${b} ${d} ${HM} ${y}" +"%Y-%m-%d %H:%M" - else - printf "%-${WIDTH_NAME}s %-6s %-${WIDTH_MOUNT}s %6s " ${NAME} ${ACTIVE} ${MOUNT} ${TOTAL} - date -j -f "%a %b %d %H:%M %Y" "${a} ${b} ${d} ${HM} ${y}" +"%Y-%m-%d %H:%M" - fi - done + else { + SPACE = 0 + ACTIVE = "" + NAME = BENAME_BEGINS_WITH "/" BENAME + if(NAME == ROOTFS) + ACTIVE = ACTIVE "N" + if(NAME == BOOTFS) + ACTIVE = ACTIVE "R" + if(! ACTIVE) + ACTIVE = "-" + for(J = 1; J <= length(FSNAMES); J++) { + FSNAME = FSNAMES[J] + if(FSNAME ~ "^" BENAME_BEGINS_WITH "/" BENAME "(/[^@]*)?$") { + if((BENAME_BEGINS_WITH "/" BENAME) == FSNAME) { + MOUNTPOINT = MOUNTS[FSNAME] + CREATION = __convert_date(CREATIONS[FSNAME]) + } + SPACE += SPACES[FSNAME] + ORIGIN = ORIGINS[FSNAME] + if(ORIGIN != "-") { + if(OPTION_D == 1) + SPACE += REFER[ORIGIN] + else + SPACE += SPACES[ORIGIN] + } + } + } + printf "%-" FSNAME_LENGTH "s %-6s %-" MOUNTPOINT_LENGTH "s %6s %s\n", BENAME, ACTIVE, MOUNTPOINT, __show_units(SPACE), CREATION + } + } + }' ;; (create) # ------------------------------------------------------------------