diff --git a/90zfsbootmenu/zfs-chroot.sh b/90zfsbootmenu/zfs-chroot.sh index 6dedb4a7..f29cf348 100755 --- a/90zfsbootmenu/zfs-chroot.sh +++ b/90zfsbootmenu/zfs-chroot.sh @@ -36,7 +36,6 @@ if mountpoint="$( allow_rw=yes mount_zfs "${selected}" )"; then _SHELL="/bin/sh" else zerror "unable to test execute a shell in ${selected}" - color=red timed_prompt "Unable to find a working shell in ${selected}" fi if [ -n "${_SHELL}" ]; then @@ -45,7 +44,6 @@ if mountpoint="$( allow_rw=yes mount_zfs "${selected}" )"; then # regardless of shell, set PS1 if ! env "PS1=$( colorize orange "${selected}") > " chroot "${mountpoint}" "${_SHELL}" ; then zerror "unable to execute ${selected}:${_SHELL}" - color=red timed_prompt "Unable to chroot in to ${selected}" fi fi diff --git a/90zfsbootmenu/zfsbootmenu-countdown.sh b/90zfsbootmenu/zfsbootmenu-countdown.sh index 2ef50bd5..08f1b2dd 100755 --- a/90zfsbootmenu/zfsbootmenu-countdown.sh +++ b/90zfsbootmenu/zfsbootmenu-countdown.sh @@ -60,6 +60,7 @@ fi unsupported=0 while IFS=$'\t' read -r _pool _property; do if [[ "${_property}" =~ "unsupported@" ]]; then + zerror "unsupported property: ${_property}" if ! grep -q "${_pool}" "${BASE}/degraded" >/dev/null 2>&1 ; then echo "${_pool}" >> "${BASE}/degraded" fi @@ -68,6 +69,7 @@ while IFS=$'\t' read -r _pool _property; do done <<<"$( zpool get all -H -o name,property )" if [ "${unsupported}" -ne 0 ]; then + zerror "Unsupported features detected, Upgrade ZFS modules in ZFSBootMenu with generate-zbm" color=red timed_prompt "Unsupported features detected" "Upgrade ZFS modules in ZFSBootMenu with generate-zbm" fi diff --git a/90zfsbootmenu/zfsbootmenu-exec.sh b/90zfsbootmenu/zfsbootmenu-exec.sh index c76525a9..641d985c 100755 --- a/90zfsbootmenu/zfsbootmenu-exec.sh +++ b/90zfsbootmenu/zfsbootmenu-exec.sh @@ -8,12 +8,7 @@ export loglevel export root export zbm_sort -# store current kernel log level -read -r PRINTK < /proc/sys/kernel/printk -PRINTK=${PRINTK:0:1} -export PRINTK - -# Set it to 0 +# Disable all kernel messages to the console echo 0 > /proc/sys/kernel/printk # set the console size, if indicated @@ -31,6 +26,7 @@ fi echo "Loading ZFSBootMenu ..." export BASE="/zfsbootmenu" +mkdir -p "${BASE}" modprobe zfs 2>/dev/null udevadm settle @@ -44,7 +40,7 @@ udevadm settle #shellcheck disable=SC2154 if [ -n "${zbm_tmux}" ] && [ -x /bin/tmux ]; then tmux new-session -n ZFSBootMenu -d /libexec/zfsbootmenu-countdown - tmux new-window -n logs /bin/zlogtail + tmux new-window -n logs /bin/zlogtail -f -n tmux new-window -n shell /bin/bash exec tmux attach-session \; select-window -t ZFSBootMenu else diff --git a/90zfsbootmenu/zfsbootmenu-lib.sh b/90zfsbootmenu/zfsbootmenu-lib.sh index c4fef3fa..fa9235e9 100755 --- a/90zfsbootmenu/zfsbootmenu-lib.sh +++ b/90zfsbootmenu/zfsbootmenu-lib.sh @@ -21,7 +21,8 @@ zlog() { _script="$( basename $0 )" _func="${FUNCNAME[2]}" - echo -e "<${1}>ZBM:\033[0;33m${_script}[$$]\033[0;31m:${_func}()\033[0m: ${2}" > /dev/kmsg + WIDTH="$( tput cols )" + echo -e "<${1}>ZBM:\033[0;33m${_script}[$$]\033[0;31m:${_func}()\033[0m: ${2}" | fold -s -w "${WIDTH}" > /dev/kmsg } # arg1: log line @@ -41,6 +42,7 @@ zwarn() { } zerror() { + : > "${BASE}/have_errors" zlog 3 "$@" } @@ -107,6 +109,12 @@ mount_zfs() { local fs rwo mnt ret pool is_snapshot fs="${1}" + + if [ -z "${fs}" ]; then + zerror "fs is undefined" + return 1 + fi + if be_is_locked "${fs}" >/dev/null; then zdebug "${fs} is locked, returning" return 1 @@ -250,12 +258,19 @@ draw_be() { local env selected header expects env="${1}" + if [ -z "${env}" ]; then + zerror "environment file is undefined" + return 130 + fi - zdebug "using environment file: ${env}" + if [ ! -r "${env}" ] ; then + zerror "environment file ${env} is missing" + return 130 + fi - [ -r "${env}" ] || return 130 + zdebug "using environment file: ${env}" - header="$( header_wrap "[ENTER] boot" "[ESC] refresh view" "[CTRL+H] help" "" \ + header="$( header_wrap "[ENTER] boot" "[ESC] refresh view" "[CTRL+H] help" "[CTRL+L] error log" "" \ "[CTRL+E] edit kcl" "[CTRL+K] kernels" "[CTRL+D] set bootfs" "[CTRL+S] snapshots" "" \ "[CTRL+I] interactive chroot" "[CTRL+R] recovery shell" "[CTRL+P] pool status" )" @@ -284,14 +299,21 @@ draw_kernel() { local benv selected header expects _kernels benv="${1}" + if [ -z "${benv}" ]; then + zerror "benv is undefined" + return 130 + fi + _kernels="${BASE}/${benv}/kernels" + if [ ! -r "${_kernels}" ] ; then + zerror "kernel file ${_kernels} missing" + return 130 + fi zdebug "using kernels file: ${_kernels}" - [ -r "${_kernels}" ] || return 130 - header="$( header_wrap \ - "[ENTER] boot" "[ESC] back" "" "[CTRL+D] set default" "[CTRL+H] help" )" + "[ENTER] boot" "[ESC] back" "" "[CTRL+D] set default" "[CTRL+H] help" "[CTRL+L] error log" )" expects="--expect=alt-d" @@ -319,13 +341,16 @@ draw_snapshots() { local benv selected header expects sort_key benv="${1}" - + if [ -z "${benv}" ]; then + zerror "benv is undefined" + return 130 + fi zdebug "using boot environment: ${benv}" sort_key="$( get_sort_key )" header="$( header_wrap \ - "[ENTER] duplicate" "[ESC] back" "[CTRL+H] help" "" \ + "[ENTER] duplicate" "[ESC] back" "[CTRL+H] help" "[CTRL+L] error log" "" \ "[CTRL+X] clone and promote" "[CTRL+C] clone only" "" \ "[CTRL+I] interactive chroot" "[CTRL+D] show diff" )" @@ -357,9 +382,13 @@ draw_diff() { local snapshot pool diff_target mnt snapshot="${1}" - pool="${snapshot%%/*}" - + if [ -z "${snapshot}" ]; then + zerror "snapshot is undefined" + return 130 + fi zdebug "snapshot: ${snapshot}" + + pool="${snapshot%%/*}" zdebug "pool: ${pool}" if ! set_rw_pool "${pool}"; then @@ -378,14 +407,14 @@ draw_diff() { fi # shellcheck disable=SC2016 - ( zfs diff -F -H "${snapshot}" "${diff_target}" & echo $! >&3 ) 3>/tmp/diff.pid | \ + ( zfs diff -F -H "${snapshot}" "${diff_target}" & echo $! >&3 ) 3>"${BASE}/diff.pid" | \ sed "s,${mnt},," | \ HELP_SECTION=DIFF ${FUZZYSEL} --prompt "${snapshot} > " \ --preview="/libexec/zfsbootmenu-preview ${diff_target} ${BOOTFS}" \ --preview-window="up:${PREVIEW_HEIGHT}" \ - --bind 'esc:execute-silent( kill $( cat /tmp/diff.pid ) )+abort' + --bind 'esc:execute-silent[ kill $( cat ${BASE}/diff.pid ) ]+abort' - rm -f /tmp/diff.pid + rm -f "${BASE}/diff.pid" umount "${mnt}" return @@ -401,7 +430,7 @@ draw_pool_status() { # Wrap to half width to avoid the preview window hdr_width="$(( ( $( tput cols ) / 2 ) - 4 ))" header="$( wrap_width="$hdr_width" header_wrap \ - "[ESC] back" "" "[CTRL+R] rewind checkpoint" "" "[CTRL+H] help" )" + "[ESC] back" "" "[CTRL+R] rewind checkpoint" "" "[CTRL+H] help" "[CTRL+L] error log" )" if ! selected="$( zpool list -H -o name | HELP_SECTION=POOL ${FUZZYSEL} \ @@ -426,6 +455,10 @@ kexec_kernel() { local selected fs kernel initramfs tdhook output selected="${1}" + if [ -z "${selected}" ]; then + zerror "fs, kernel, initramfs undefined" + return 130 + fi # zfs filesystem # kernel @@ -447,13 +480,6 @@ kexec_kernel() { cli_args="$( load_be_cmdline "${fs}" )" root_prefix="$( find_root_prefix "${fs}" "${mnt}" )" - # restore kernel log level just before we kexec - # shellcheck disable=SC2154 - if [ -n "${PRINTK}" ] ; then - echo "${PRINTK}" > /proc/sys/kernel/printk - zdebug "restored kernel log level to ${PRINTK}" - fi - if ! output="$( kexec -l "${mnt}${kernel}" \ --initrd="${mnt}${initramfs}" \ --command-line="${root_prefix}${fs} ${cli_args}" 2>&1 )" @@ -461,6 +487,10 @@ kexec_kernel() { zerror "unable to load ${mnt}${kernel} and ${mnt}${initramfs} into memory" zerror "${output}" umount "${mnt}" + color=red delay=10 timed_prompt "Unable to load kernel or initramfs into memory" \ + "${mnt}${kernel}" \ + "${mnt}${initramfs}" + return 1 else zdebug "loaded ${mnt}${kernel} and ${mnt}${initramfs} into memory" @@ -487,7 +517,9 @@ kexec_kernel() { fi if ! output="$( kexec -e -i 2>&1 )"; then - zdebug "${output}" + zerror "kexec -e -i failed!" + zerror "${output}" + color=red delay=10 timed_prompt "kexec run of ${kernel} failed!" return 1 fi } @@ -501,16 +533,24 @@ duplicate_snapshot() { local selected target target_parent pool recv_args selected="${1}" - target="${2}" - - [ -n "$selected" ] || return 1 - [ -n "$target" ] || return 1 - + if [ -z "$selected" ]; then + zerror "selected is undefined" + return 1 + fi zdebug "selected: ${selected}" + + target="${2}" + if [ -z "$target" ]; then + zerror "target is undefined" + return 1 + fi zdebug "target: ${target}" pool="${selected%%/*}" - set_rw_pool "${pool}" || return 1 + if ! set_rw_pool "${pool}" ; then + zerror "unable to set pool ${pool} read/write" + return 1 + fi # Make sure both the source and the parent of the target are unlocked # NOTE: load_key should work as expected without stripping snapshot from name @@ -545,21 +585,32 @@ duplicate_snapshot() { clone_snapshot() { local selected target pool opts parent - selected="${1}" - target="${2}" promote="${3}" - [ -n "$selected" ] || return 1 - [ -n "$target" ] || return 1 - + selected="${1}" + if [ -z "$selected" ]; then + zerror "selected is undefined" + return 1 + fi zdebug "selected: ${selected}" + + target="${2}" + if [ -z "$target" ]; then + zerror "target is undefined" + return 1 + fi zdebug "target: ${target}" + + promote="${3}" zdebug "promote: ${promote}" pool="${selected%%/*}" - parent="${selected%%@*}" + if ! set_rw_pool "${pool}" ; then + zerror "unable to set pool ${pool} read/write" + return 1 + fi - set_rw_pool "${pool}" || return 1 + parent="${selected%%@*}" load_key "${parent}" while read -r PROPERTY VALUE @@ -605,11 +656,17 @@ set_default_kernel() { local fs kernel fs="$1" - [ -n "${fs}" ] || return 1 + if [ -z "${fs}" ]; then + zerror "fs is undefined" + return 1 + fi zdebug "fs set to ${fs}" pool="${fs%%/*}" - [ -n "${pool}" ] || return 1 + if [ -z "${pool}" ]; then + zerror "pool is undefined" + return 1 + fi zdebug "pool set to ${pool}" # Strip /boot/ to list only the file @@ -638,18 +695,27 @@ set_default_env() { local environment pool environment="${1}" - [ -n "${environment}" ] || return 1 + if [ -z "${environment}" ] ; then + zerror "environment is undefined" + return 1 + fi zdebug "environment set to: ${environment}" pool="${environment%%/*}" zdebug "pool set to: ${pool}" + if ! set_rw_pool "${pool}" ; then + zerror "unable to set pool ${pool} read/write" + return 1 + fi - set_rw_pool "${pool}" || return 1 CLEAR_SCREEN=1 load_key "${pool}" if zpool set bootfs="${environment}" "${pool}" >/dev/null 2>&1 ; then BOOTFS="${environment}" zdebug "BOOTFS set to ${BOOTFS}" + else + zerror "unable to set bootfs=${environment} on ${pool}" + return 1 fi } @@ -659,12 +725,16 @@ set_default_env() { find_be_kernels() { local fs mnt - fs="${1}" - - local kernel kernel_base labels version kernel_records local defaults def_kernel def_kernel_file + fs="${1}" + if [ -z "${fs}" ]; then + zerror "fs is undefined" + return 1 + fi + zdebug "fs set to ${fs}" + # Try to mount, just skip the list otherwise if ! mnt="$( mount_zfs "${fs}" )"; then zerror "unable to mount ${fs}" @@ -750,10 +820,14 @@ find_be_kernels() { # returns: nothing select_kernel() { - local zfsbe - zfsbe="${1}" + local zfsbe specific_kernel kexec_args spec_kexec_args - local specific_kernel kexec_args spec_kexec_args + zfsbe="${1}" + if [ -z "${zfsbe}" ]; then + zerror "zfsbe is undefined" + return 1 + fi + zdebug "zfsbe set to ${zfsbe}" # By default, select the last kernel entry kexec_args="$( tail -1 "${BASE}/${zfsbe}/kernels" )" @@ -773,6 +847,7 @@ select_kernel() { done <<<"$( tac "${BASE}/${zfsbe}/kernels" )" fi + zdebug "using kexec args: ${kexec_args}" echo "${kexec_args}" } @@ -782,8 +857,20 @@ select_kernel() { find_root_prefix() { local zfsbe_mnt zfsbe_fs prefix + zfsbe_fs="${1}" + if [ -z "${zfsbe_fs}" ]; then + zerror "zfsbe_fs is undefined" + return 1 + fi + zdebug "zfsbe_fs set to ${zfsbe_fs}" + zfsbe_mnt="${2}" + if [ -z "${zfsbe_mnt}" ]; then + zerror "zfsbe_mnt is undefined" + return 1 + fi + zdebug "zfsbe_mnt set to ${zfsbe_mnt}" # Grab the root prefix from a property if possible if prefix="$( zfs get -H -o value org.zfsbootmenu:rootprefix "${zfsbe_fs}" )"; then @@ -845,8 +932,20 @@ find_root_prefix() { preload_be_cmdline() { local zfsbe_mnt zfsbe_fs zfsbe_args args_file + zfsbe_fs="${1}" + if [ -z "${zfsbe_fs}" ]; then + zerror "zfsbe_fs is undefined" + return 1 + fi + zdebug "zfsbe_fs set to ${zfsbe_fs}" + zfsbe_mnt="${2}" + if [ -z "${zfsbe_mnt}" ]; then + zerror "zfsbe_mnt is undefined" + return 1 + fi + zdebug "zfsbe_mnt set to ${zfsbe_mnt}" args_file="${BASE}/${zfsbe_fs}/cmdline" @@ -882,7 +981,13 @@ preload_be_cmdline() { load_be_cmdline() { local zfsbe_fs zfsbe_args + zfsbe_fs="${1}" + if [ -z "${zfsbe_fs}" ]; then + zerror "zfsbe_fs is undefined" + return 1 + fi + zdebug "zfsbe_fs set to ${zfsbe_fs}" # If a user-entered cmdline is found, it is not modified if [ -r "${BASE}/cmdline" ]; then @@ -954,6 +1059,9 @@ import_pool() { local pool import_args pool="${1}" + if [ -n "${pool}" ]; then + zdebug "pool set to ${pool}" + fi # Import /never/ mounts filesystems import_args=( "-N" ) @@ -1001,9 +1109,13 @@ import_pool() { export_pool() { local pool - pool="${1}" - zdebug "pool: ${pool}" + pool="${1}" + if [ -z "${pool}" ]; then + zerror "pool is undefined" + return 1 + fi + zdebug "pool set to ${pool}" # shellcheck disable=SC2034 status="$( zpool export "${pool}" )" @@ -1021,6 +1133,11 @@ export_pool() { rewind_checkpoint() { local pool checkpoint pool="${1}" + if [ -z "${pool}" ]; then + zerror "pool is undefined" + return 1 + fi + zdebug "pool set to ${pool}" while read -r line; do case "$line" in @@ -1128,7 +1245,11 @@ resume_prompt() { local pool decision pool="${1}" - [ -n "${pool}" ] || return 1 + if [ -z "${pool}" ]; then + zerror "pool is undefined" + return 1 + fi + zdebug "pool set to ${pool}" # Try to avoid importing writable when a resume device is found if has_resume_device; then @@ -1190,7 +1311,11 @@ is_writable() { local pool roflag pool="${1}" - [ -n "${pool}" ] || return 1 + if [ -z "${pool}" ]; then + zerror "pool is undefined" + return 1 + fi + zdebug "pool set to ${pool}" # Pool is not writable if the property can't be read roflag="$( zpool get -H -o value readonly "${pool}" 2>/dev/null )" || return 1 @@ -1212,10 +1337,11 @@ set_rw_pool() { local pool ret pool="${1}" - - zdebug "pool: ${pool}" - - [ -n "${pool}" ] || return 1 + if [ -z "${pool}" ]; then + zerror "pool is undefined" + return 1 + fi + zdebug "pool set to ${pool}" # If force_export is set, skip evaluating if the pool is already read-write # shellcheck disable=SC2154 @@ -1249,7 +1375,14 @@ set_rw_pool() { be_has_encroot() { local fs pool encroot + fs="${1}" + if [ -z "${fs}" ]; then + zerror "fs is undefined" + return 1 + fi + zdebug "fs set to ${fs}" + pool="${fs%%/*}" if [ "$( zpool list -H -o feature@encryption "${pool}" )" != "active" ]; then @@ -1276,7 +1409,13 @@ be_has_encroot() { be_is_locked() { local fs keystatus encroot + fs="${1}" + if [ -z "${fs}" ]; then + zerror "fs is undefined" + return 1 + fi + zdebug "fs set to ${fs}" if encroot="$( be_has_encroot "${fs}" )"; then zdebug "${encroot} discovered as encryption root for ${fs}" @@ -1302,7 +1441,13 @@ be_is_locked() { be_keysource() { local fs keysrc + fs="${1}" + if [ -z "${fs}" ]; then + zerror "fs is undefined" + return 1 + fi + zdebug "fs set to ${fs}" if ! keysrc="$( zfs get -H -o value org.zfsbootmenu:keysource "${fs}" )"; then zwarn "failed to read org.zfsbootmenu:keysource on ${fs}" @@ -1332,8 +1477,20 @@ be_keysource() { cache_key() { local fs keylocation keyfile keydir keysrc keycache mutex mnt ret + fs="${1}" + if [ -z "${fs}" ]; then + zerror "fs is undefined" + return 1 + fi + zdebug "fs set to ${fs}" + keylocation="${2}" + if [ -z "${keylocation}" ]; then + zerror "keylocation is undefined" + return 1 + fi + zdebug "keylocation set to ${keylocation}" # Strip scheme if it exists keyfile="${keylocation#file://}" @@ -1418,7 +1575,13 @@ cache_key() { load_key() { local fs encroot key keypath keyformat keylocation keysource + fs="${1}" + if [ -z "${fs}" ]; then + zerror "fs is undefined" + return 1 + fi + zdebug "fs set to ${fs}" # Nothing to do if filesystem is not locked if ! encroot="$( be_is_locked "${fs}" )" || [ -z "$encroot" ]; then @@ -1503,7 +1666,11 @@ populate_be_list() { local be_list fs mnt active candidates ret sort_key be_list="${1}" - [ -n "${be_list}" ] || return 1 + if [ -z "${be_list}" ]; then + zerror "be_list is undefined" + return 1 + fi + zdebug "be_list set to ${be_list}" sort_key="$( get_sort_key )" @@ -1553,8 +1720,13 @@ populate_be_list() { zfs_chroot() { local fs + fs="${1}" - [ -n "${fs}" ] || return + if [ -z "${fs}" ]; then + zerror "fs is undefined" + return 1 + fi + zdebug "fs set to ${fs}" tput clear tput cnorm diff --git a/90zfsbootmenu/zfsbootmenu-parse-commandline.sh b/90zfsbootmenu/zfsbootmenu-parse-commandline.sh index 3ddfbb76..833b6f80 100755 --- a/90zfsbootmenu/zfsbootmenu-parse-commandline.sh +++ b/90zfsbootmenu/zfsbootmenu-parse-commandline.sh @@ -29,6 +29,8 @@ fi # Use loglevel to determine logging to /dev/kmsg loglevel=$( getarg loglevel=) if [ -n "${loglevel}" ]; then + # minimum log level of 3, so we never lose error messages + [ "${loglevel}" -ge 3 ] || loglevel=3 info "ZFSBootMenu: setting log level from command line: ${loglevel}" else loglevel=3 diff --git a/90zfsbootmenu/zfsbootmenu-preview.sh b/90zfsbootmenu/zfsbootmenu-preview.sh index a3591f10..7d781ce5 100755 --- a/90zfsbootmenu/zfsbootmenu-preview.sh +++ b/90zfsbootmenu/zfsbootmenu-preview.sh @@ -26,11 +26,16 @@ else _DEFAULT="" fi -selected_env_str="$( center_string "${ENV} (${_DEFAULT}${_readonly}) - ${selected_kernel}" )" - selected_arguments="$( load_be_cmdline "${ENV}" )" selected_arguments="$( center_string "$( load_be_cmdline "${ENV}" )" )" +selected_env_str="$( center_string "${ENV} (${_DEFAULT}${_readonly}) - ${selected_kernel}" )" + # colorize doesn't automatically add a newline +if [ -f "${BASE}/have_errors" ]; then + selected_env_str="${selected_env_str:3}" + colorize "red" "[!]" +fi + colorize "${_COLOR}" "${selected_env_str}\n" echo "${selected_arguments}" diff --git a/90zfsbootmenu/zfsbootmenu.sh b/90zfsbootmenu/zfsbootmenu.sh index 9c3d6be2..d002f1d4 100755 --- a/90zfsbootmenu/zfsbootmenu.sh +++ b/90zfsbootmenu/zfsbootmenu.sh @@ -60,7 +60,10 @@ fuzzy_default_options=( "--ansi" "--no-clear" "--layout=reverse-list" "--inline-info" "--tac" "--color=16" "--bind" '"alt-h:execute[ /libexec/zfsbootmenu-help -L ${HELP_SECTION:-MAIN} ]"' "--bind" '"ctrl-h:execute[ /libexec/zfsbootmenu-help -L ${HELP_SECTION:-MAIN} ]"' - "--bind" '"ctrl-alt-h:execute[ /libexec/zfsbootmenu-help -L ${HELP_SECTION:-MAIN} ]"' ) + "--bind" '"ctrl-alt-h:execute[ /libexec/zfsbootmenu-help -L ${HELP_SECTION:-MAIN} ]"' + "--bind" '"alt-l:execute[ /bin/zlogtail -l err -F user -c ]+refresh-preview"' + "--bind" '"ctrl-l:execute[ /bin/zlogtail -l err -F user -c ]+refresh-preview"' + "--bind" '"ctrl-alt-l:execute[ /bin/zlogtail -l err -F user -c ]+refresh-preview"' ) if command -v fzf >/dev/null 2>&1; then zdebug "using fzf for pager" export FUZZYSEL=fzf @@ -209,6 +212,7 @@ while true; do if [ "${leftover_space}" -le 0 ]; then avail_space="$( zfs list -H -o available "${parent_ds}" )" be_size="$( zfs list -H -o refer "${selected_snap}" )" + zerror "Insufficient space for duplication, ${parent_ds}' has ${avail_space} free but needs ${be_size}" color=red delay=10 timed_prompt "Insufficient space for duplication" \ "'${parent_ds}' has ${avail_space} free but needs ${be_size}" continue @@ -280,7 +284,7 @@ while true; do tput cnorm echo "" - /libexec/zfsbootmenu-preview "${BASE}" "${selected_be}" "${BOOTFS}" + /libexec/zfsbootmenu-preview "${selected_be}" "${BOOTFS}" BE_ARGS="$( load_be_cmdline "${selected_be}" )" while IFS= read -r line; do diff --git a/90zfsbootmenu/zlogtail.sh b/90zfsbootmenu/zlogtail.sh index c2b538b7..a4ce41e1 100755 --- a/90zfsbootmenu/zlogtail.sh +++ b/90zfsbootmenu/zlogtail.sh @@ -1,14 +1,61 @@ #!/bin/bash -# Ignore keys in a future release -# --bind "ctrl-c:ignore,ctrl-g:ignore,esc:ignore,enter:ignore" +PID_FILE="$( mktemp --tmpdir="${BASE}" )" +export PID_FILE +trap 'rm -f ${PID_FILE}' EXIT + +#shellcheck disable=SC2154 +LOG_LEVEL="0,1,2,3,4,5,6,7" +FACILITY="kern,user" +FOLLOW="" +ALLOW_EXIT=1 +while getopts "cfnl:F:" opt; do + case "${opt}" in + l) + LOG_LEVEL="${OPTARG}" + ;; + n) + ALLOW_EXIT=0 + ;; + f) + FOLLOW="-w" + ;; + c) + [ -f "${BASE}/have_errors" ] && rm "${BASE}/have_errors" + ;; + F) + FACILITY="${OPTARG}" + ;; + *) + ;; + esac +done + +fuzzy_default_options+=("--no-sort") +fuzzy_default_options+=("--ansi") +fuzzy_default_options+=("--tac") + +fuzzy_default_options+=("--bind") +fuzzy_default_options+=('"ctrl-q:ignore,ctrl-c:ignore,ctrl-g:ignore,enter:ignore"') + +if ((ALLOW_EXIT)) ; then + fuzzy_default_options+=("--bind") + # shellcheck disable=SC2016 + fuzzy_default_options+=('"esc:execute-silent[ kill $( cat ${PID_FILE} ) ]+abort"') +else + fuzzy_default_options+=("--bind") + fuzzy_default_options+=('"esc:ignore"') +fi if command -v fzf >/dev/null 2>&1; then FUZZYSEL=fzf - export FZF_DEFAULT_OPTS='--no-mouse --no-sort --ansi --tac --no-info' + export FZF_DEFAULT_OPTS="--no-mouse --no-info ${fuzzy_default_options[*]}" elif command -v sk >/dev/null 2>&1; then FUZZYSEL=sk - export SKIM_DEFAULT_OPTIONS='--no-sort --ansi --tac' + export SKIM_DEFAULT_OPTIONS="${fuzzy_default_options[*]}" fi -dmesg -T --time-format reltime --noescape -w | ${FUZZYSEL} + # shellcheck disable=SC2086 +( dmesg -T --time-format reltime --noescape -f ${FACILITY} -l ${LOG_LEVEL} ${FOLLOW} & echo $! >&3 ) \ + 3>"${PID_FILE}" \ + | ${FUZZYSEL}