From 9da78f3b703df721eb9e2c77c6f2e1456c9f4cc1 Mon Sep 17 00:00:00 2001 From: Ian Kelling Date: Tue, 12 Nov 2019 12:58:47 -0500 Subject: [PATCH] etiona fixes, new bash-trace --- bash-trace | 2 +- debian-pxe-preseed | 2 +- dsfull | 4 +- fai-revm | 4 +- fai/config/files/boot/bash-trace/DEFAULT | 333 +++++++++--------- .../apt/preferences.d/etiona-bionic/ETIONA | 12 + faiserver-revm | 4 +- mk-basefile-big | 2 +- 8 files changed, 196 insertions(+), 167 deletions(-) diff --git a/bash-trace b/bash-trace index 7656675..015ae24 120000 --- a/bash-trace +++ b/bash-trace @@ -1 +1 @@ -./fai/config/files/boot/bash-trace/DEFAULT \ No newline at end of file +fai/config/files/boot/bash-trace/DEFAULT \ No newline at end of file diff --git a/debian-pxe-preseed b/debian-pxe-preseed index bac251a..094294a 100755 --- a/debian-pxe-preseed +++ b/debian-pxe-preseed @@ -28,7 +28,7 @@ e() { echo "$*"; "$@"; } mount_dir=$(mktemp -d) -errcatch-cleanup() { cd; umount -f $mount_dir; } +err-cleanup() { cd; umount -f $mount_dir; } e mount -o users wrt:/mnt/usb $mount_dir diff --git a/dsfull b/dsfull index cdb840b..91ab8ec 100755 --- a/dsfull +++ b/dsfull @@ -70,7 +70,7 @@ if $kexec; then myfai-chboot $host live-kexec $host ||: else - errcatch-cleanup() { pxe-server; } + err-cleanup() { pxe-server; } pxe-server $host fai if $reboot; then @@ -79,7 +79,7 @@ else fi pxe-server -a - unset errcatch-cleanup + unset err-cleanup fi error=true diff --git a/fai-revm b/fai-revm index a44b218..9fa0787 100755 --- a/fai-revm +++ b/fai-revm @@ -87,7 +87,7 @@ is_arch_revm() { [[ ${0##*/} == arch-revm ]] } -errcatch-cleanup() { +err-cleanup() { echo "doing cleanup" e ./pxe-server $dhcp_arg ./faiserver-disable @@ -170,7 +170,7 @@ sleep 30 while ! timeout -s 9 10 ssh -oBatchMode=yes root@$name /bin/true; do e sleep 5 done -unset errcatch-cleanup +unset err-cleanup e ./pxe-server $dhcp_arg if is_arch_revm; then ./arch-init-remote $name diff --git a/fai/config/files/boot/bash-trace/DEFAULT b/fai/config/files/boot/bash-trace/DEFAULT index 246042d..dc1a218 100644 --- a/fai/config/files/boot/bash-trace/DEFAULT +++ b/fai/config/files/boot/bash-trace/DEFAULT @@ -1,203 +1,220 @@ #!/bin/bash # Copyright (C) 2019 Ian Kelling -# SPDX-License-Identifier: AGPL-3.0-or-later +# SPDX-License-Identifier: GPL-3.0-or-later -# meant to be sourced. copy/pasted from https://iankelling.org/git/?p=errhandle;a=summary +# Commentary: Print stack trace and exit/return on errors, or use +# functions below for for more details and manual error handling. See +# end of file for credits etc. -# Commentary: Bash stack trace and error handling functions. This file -# is meant to be sourced. It loads some functions which you may want to -# call manually (see the comments at the start of each one), and then -# runs err-catch. See the README file for a slightly longer explanation. +####################################### +# err-catch: Setup trap on ERR to print stack trace and exit (or return +# if the shell is interactive). This is the most common use case so we +# run it after defining it, you can call err-allow to undo that. +# +# This also sets pipefail because it's a good practice to catch more +# errors. +# +# Note: In interactive shell, stack calling line number is not +# available, so we print function definition lines. +# +# Globals +# +# err_catch_ignore Array containing glob patterns to test against +# filenames to ignore errors from in interactive +# shell. Initialized to ignore bash-completion +# scripts on debian based systems. +# +# err-cleanup If set, this command will run just before exiting. +# +# _err_func_last Used internally in err-bash-trace-interactive +# +####################################### +err-catch() { + set -E; + if [[ $- == *i* ]]; then + if ! test ${err_catch_ignore+defined}; then + err_catch_ignore=( + '/etc/bash_completion.d/*' + '*/bash-completion/*' + ) + fi + declare -i _err_func_last=0 + shopt -s extdebug + # shellcheck disable=SC2154 + trap '_err-bash-trace-interactive $? "$BASH_COMMAND" ${BASH_ARGC[0]} "${BASH_ARGV[@]}" || return $?' ERR + else + # Man bash on exdebug: "If set at shell invocation, arrange to + # execute the debugger". We want to avoid that, but I want this file + # to be sourceable from bash startup files. noninteractive ssh and + # sources .bashrc on invocation. login_shell sources things on + # invocation. + # + # extdebug allows us to print function arguments in our stack trace. + if ! shopt login_shell >/dev/null && [[ ! $SSH_CONNECTION ]]; then + shopt -s extdebug + fi + trap err-exit ERR + fi + set -o pipefail +} +# This is the most common use case so run it now. +err-catch +####################################### +# Undo err-catch/err-catch-interactive +####################################### +err-allow() { + shopt -u extdebug + set +E +o pipefail + trap ERR +} + +####################################### +# err-exit: Print stack trace and exit +# +# Use this instead of the exit command to be more informative. +# +# usage: err-exit [-EXIT_CODE] [MESSAGE] +# +# EXIT_CODE Default: $? if it is nonzero, otherwise 1. +# MESSAGE Print MESSAGE to stderr. Default: +# ${BASH_SOURCE[1]}:${BASH_LINENO[0]}: `$BASH_COMMAND' returned $? +# +# Globals +# +# err-cleanup If set, this command will run just before exiting. +# +####################################### +err-exit() { + local err=$? + # This has to come before most things or vars get changed + local msg="${BASH_SOURCE[1]}:${BASH_LINENO[0]}: \`$BASH_COMMAND' returned $err" + set +x + if [[ $1 == -* ]]; then + err=${1#-} + shift + elif (( ! err )); then + err=1 + fi + if [[ $1 ]]; then + msg="$1" + fi + printf "%s\n" "$msg" >&2 + err-bash-trace 2 + set -e # err trap does not work within an error trap + if type -t err-cleanup >/dev/null; then + err-cleanup + fi + printf "%s: exiting with status %s\n" "$0" "$err" >&2 + exit $err +} ####################################### # Print stack trace # -# usage: err-bash-trace [MESSAGE] +# usage: err-bash-trace [FRAME_START] # # This function is called by the other functions which print stack # traces. # # It does not show function args unless you first run: # shopt -s extdebug -# which err-catch & err-print do for you. +# which err-catch does for you. # -# MESSAGE Message to print just before the stack trace. +# FRAME_START Optional variable to set before calling. The frame to +# start printing on. default=1. If ${#FUNCNAME[@]} <= +# FRAME_START + 1, don't print anything because we are at +# the top level of the script and better off printing a +# general message, for example see what our callers print. # -# _frame_start Optional variable to set before calling. The frame to -# start printing on. default=1. Useful when printing from -# an ERR trap function to avoid printing that function. ####################################### err-bash-trace() { - local -i argc_index=0 frame i start=${_frame_start:-1} - local source - if [[ $1 ]]; then - printf "%s\n" "$1" + local -i argc_index=0 frame i frame_start=${1:-1} + local source_loc + if (( ${#FUNCNAME[@]} <= frame_start + 1 )); then + return 0 fi for ((frame=0; frame < ${#FUNCNAME[@]}; frame++)); do argc=${BASH_ARGC[frame]} argc_index+=$argc - ((frame < start)) && continue + if ((frame < frame_start)); then continue; fi if (( ${#BASH_SOURCE[@]} > 1 )); then - source="${BASH_SOURCE[frame]}:${BASH_LINENO[frame-1]}:" + source_loc="${BASH_SOURCE[frame]}:${BASH_LINENO[frame-1]}:" fi - printf " from %sin \`%s" "$source" "${FUNCNAME[frame]}" + printf " from %sin \`%s" "$source_loc" "${FUNCNAME[frame]}" >&2 if shopt extdebug >/dev/null; then for ((i=argc_index-1; i >= argc_index-argc; i--)); do - printf " %s" "${BASH_ARGV[i]}" + printf " %s" "${BASH_ARGV[i]}" >&2 done fi - echo \' + echo \' >&2 done return 0 } ####################################### -# On error print stack trace and exit +# Internal function for err-catch. Prints stack trace from interactive +# shell trap. # -# Globals: -# errcatch-cleanup If set, this command will run just before exiting. +# Usage: see err-catch-interactive ####################################### -err-catch() { - set -E; shopt -s extdebug - _err-trap() { - err=$? - exec >&2 - set +x - local msg="${BASH_SOURCE[1]}:${BASH_LINENO[0]}: \`$BASH_COMMAND' returned $err" - if (( ${#FUNCNAME[@]} > 2 )); then - local _frame_start=2 - err-bash-trace "$msg" - else - echo "$msg" - fi - set -e # err trap does not work within an error trap - if type -t errcatch-cleanup >/dev/null; then - errcatch-cleanup - fi - echo "$0: exiting with status $err" - exit $err - } - trap _err-trap ERR - set -o pipefail -} - +_err-bash-trace-interactive() { + if (( ${#FUNCNAME[@]} <= 1 )); then + return 0 + fi -####################################### -# For interactive shells: on error, print stack trace and return -# -# Globals: -# err_catch_ignore Array containing glob patterns to test against filenames to ignore -# errors from. Initialized to ignore bash-completion scripts on debian -# based systems. -# _err_func_last Used internally. -# _err_catch_err Used internally. -# _err_catch_i Used internally. -# _err_catch_ignore Used internally. -# -# misc: All shellcheck disables for this function are false positives. -####################################### -# shellcheck disable=SC2120 -err-catch-interactive() { - err_catch_ignore=( - '/etc/bash_completion.d/*' - ) - # shellcheck disable=SC2034 - declare -i _err_func_last=0 - set -E; shopt -s extdebug - # shellcheck disable=SC2154 - trap '_err_catch_err=$? _trap_bc="$BASH_COMMAND" - _err_catch_ignore=false - for _err_catch_i in "${err_catch_ignore[@]}"; do - if [[ ${BASH_SOURCE[0]} == $_err_catch_i ]]; then - _err_catch_ignore=true - break + for pattern in "${err_catch_ignore[@]}"; do + # shellcheck disable=SC2053 + if [[ ${BASH_SOURCE[1]} == $pattern ]]; then + return 0 fi done - if ! $_err_catch_ignore; then - if (( ${#FUNCNAME[@]} > _err_func_last )); then - echo ERR: \`$_trap_bc'"\'"' returned $_err_catch_err - fi - _err_func_last=${#FUNCNAME[@]} - if (( _err_func_last )); then - printf " from %s:%s:in \`%s" "${BASH_SOURCE[0]}" "$(declare -F "${FUNCNAME[0]}"|awk "{print \$2}")" "${FUNCNAME[0]}" - if shopt extdebug >/dev/null; then - for ((_err_catch_i=${BASH_ARGC[0]}-1; _err_catch_i >= 0; _err_catch_i--)); do - printf " %s" "${BASH_ARGV[_err_catch_i]}" - done - fi - echo '"\'"' - return $_err_catch_err - fi - fi' ERR - set -o pipefail -} - -####################################### -# Undoes err-catch/err-catch-interactive -####################################### -err-allow() { - shopt -u extdebug - set +E +o pipefail - trap ERR -} - -####################################### -# On error, print stack trace -####################################### -err-print() { - # help: on errors: print stack trace - # - # This function depends on err-bash-trace. - - set -E; shopt -s extdebug - _err-trap() { - err=$? - exec >&2 - set +x - echo "${BASH_SOURCE[1]}:${BASH_LINENO[0]}: \`$BASH_COMMAND' returned $err" - err-bash-trace 2 - } - trap _err-trap ERR - set -o pipefail + local ret bash_command argc pattern i last + last=$_err_func_last + _err_func_last=${#FUNCNAME[@]} + # We have these passed to us because they are lost inside the + # function. + ret=$1 + bash_command="$2" + argc=$(( $3 - 1 )) + shift 3 + argv=("$@") + # The trap returns a nonzero, then gets called again. This condition + # tells us if we are the first. + if (( _err_func_last > last )); then + printf "ERR: \`%s\' returned %s\n" "$bash_command" $ret >&2 + fi + printf " from \`%s" "${FUNCNAME[1]}" >&2 + if shopt extdebug >/dev/null; then + for ((i=argc; i >= 0; i--)); do + printf " %s" "${argv[i]}" >&2 + done + fi + printf "\' defined at %s:%s\n" "${BASH_SOURCE[1]}" "$(declare -F "${FUNCNAME[1]}"|awk "{print \$2}")" >&2 + if [[ -t 1 ]]; then + return $ret + else + # Part of an outgoing pipe, avoid getting get us stuck in a weird + # subshell if we returned nonzero, which would happen in a situation + # like this: + # + # tf() { while read -r line; do :; done < <(asdf); }; + # tf + # + # Note: exit $ret also avoids the stuck subshell problem, and I + # can't notice any difference, but this seems more proper. + return 0 + fi } - -####################################### -# Print stack trace and exit +# Credits etc: # -# Use this instead of the exit command to be more informative. +# Related: see my bash script template repo at https://iankelling.org/git. # -# usage: err-exit [EXIT_CODE] [MESSAGE] # -# EXIT_CODE Default is 1. -# MESSAGE Print MESSAGE to stderr. If only one of EXIT_CODE -# and MESSAGE is given, we consider it to be an -# exit code if it is a number. -####################################### -err-exit() { - exec >&2 - code=1 - if [[ "$*" ]]; then - if [[ ${1/[^0-9]/} == "$1" ]]; then - code=$1 - if [[ $2 ]]; then - printf '%s\n' "$2" >&2 - fi - else - printf '%s\n' "$0: $1" >&2 - fi - fi - echo "${BASH_SOURCE[1]}:${BASH_LINENO[0]}" - err-bash-trace 2 - echo "$0: exiting with code $code" - exit $err -} - -# We want this more often than not, so run it now. -if [[ $- == *i* ]]; then - err-catch-interactive -else - err-catch -fi +# Please email me if you have a patches, bugs, feedback, or if you use +# it or republish it since I'm not aware of any users yet +# Ian Kelling . +# +# Tested on bash 4.4.20(1)-release (x86_64-pc-linux-gnu). If you test diff --git a/fai/config/files/etc/apt/preferences.d/etiona-bionic/ETIONA b/fai/config/files/etc/apt/preferences.d/etiona-bionic/ETIONA index e4161f6..3a2df5a 100644 --- a/fai/config/files/etc/apt/preferences.d/etiona-bionic/ETIONA +++ b/fai/config/files/etc/apt/preferences.d/etiona-bionic/ETIONA @@ -10,6 +10,18 @@ Package: * Pin: release a=bionic-security Pin-Priority: -100 +Package: * +Pin: release n=bionic +Pin-Priority: -100 + Package: openssh-client openssh-server unattended-upgrades openssh-sftp-server aptitude aptitude-common redshift redshift-gtk gtk-redshift apache2 apache2-bin apache2-data apache2-utils firefox aptitude-doc-en apache2-doc gnome-screenshot nginx-doc p7zip p7zip-full gnome-icon-theme libnautilus-extension1a pidgin pidgin-data libpurple0 pidgin-libnotify unrar-free Pin: release n=bionic Pin-Priority: 500 + +Package: hplip cups-filters hplip-data libhpmud0 libsane-hpaio printer-driver-hpcups printer-driver-postscript-hp cups-filters-core-drivers libcupsfilters1 libfontembed1 +Pin: release n=bionic +Pin-Priority: 500 + +Package: gnome-core gnome-menus gnome-session gnome-settings-daemon nautilus system-config-printer-common system-config-printer-udev yelp gnome-session-bin gnome-settings-daemon-schemas nautilus-data ubuntu-wallpapers ubuntu-session gnome-control-center gnome-control-center-data gnome-control-center-faces language-selector-gnome libsnapd-glib1 language-selector-common python3-cupshelpers ubuntu-wallpapers-bionic gnome-session-common gir1.2-gmenu-3.0 libgnome-menu-3-0 software-properties-gtk python3-software-properties gir1.2-snapd-1 ubuntu-drivers-common software-properties-common gnome-session-bin ubuntu-docs libyelp0 +Pin: release n=bionic +Pin-Priority: 500 diff --git a/faiserver-revm b/faiserver-revm index 6e4613f..bb4650e 100755 --- a/faiserver-revm +++ b/faiserver-revm @@ -22,7 +22,7 @@ case $1 in -h|--help) usage ;; esac -errcatch-cleanup() { pxe-server :; } +err-cleanup() { pxe-server :; } ./debian-pxe-preseed -i 10.0.0.1 -u iank -g vda name=faiserver @@ -43,7 +43,7 @@ while ! scp $opts faiserver-setup root@faiserver:; do done # note: with a vm, pxe boot is turned off in the bios after it's first reboot. -errcatch-cleanup() { :; } +err-cleanup() { :; } ./pxe-server ssh $opts root@faiserver ./faiserver-setup diff --git a/mk-basefile-big b/mk-basefile-big index 337d80a..873b7ff 100755 --- a/mk-basefile-big +++ b/mk-basefile-big @@ -73,7 +73,7 @@ distro=trisquel t=/tmp/dirinstall -errcatch-cleanup() { +err-cleanup() { sed -i 's/^#LOGUSER=/LOGUSER=/' /etc/fai/fai.conf for d in proc var/lib/dpkg var/cache; do umount -R $t/$d ||: -- 2.30.2