arrays - ¿Guardar y restaurar el estado de captura? ¿Manera fácil de manejar múltiples controladores para las trampas?
bash stack (1)
¿Cuál es una buena manera de anular los controladores de captura de bash
que no pisotean permanentemente los existentes que pueden estar o no configurados? ¿Qué pasa con la gestión dinámica de cadenas arbitrarias de trampas trampa?
¿Hay alguna forma de guardar el estado actual de los controladores de captura para que puedan restaurarse más tarde?
Guarda y restaura el estado de tu controlador de trampas en Bash
Yo enviaría la siguiente implementación de pila para rastrear y restaurar el estado de captura. Usando este método, puedo empujar los cambios de la trampa y luego quitarlos cuando termine con ellos. Esto también podría usarse para encadenar muchas rutinas de captura.
Vea el siguiente archivo fuente (.trap_stack.sh)
#!/bin/bash
trap_stack_name() {
local sig=${1//[^a-zA-Z0-9]/_}
echo "__trap_stack_$sig"
}
extract_trap() {
echo ${@:3:$(($#-3))}
}
get_trap() {
eval echo $(extract_trap `trap -p $1`)
}
trap_push() {
local new_trap=$1
shift
local sigs=$*
for sig in $sigs; do
local stack_name=`trap_stack_name "$sig"`
local old_trap=$(get_trap $sig)
eval "${stack_name}"''[${#''"${stack_name}"''[@]}]=$old_trap''
trap "${new_trap}" "$sig"
done
}
trap_pop() {
local sigs=$*
for sig in $sigs; do
local stack_name=`trap_stack_name "$sig"`
local count; eval ''count=${#''"${stack_name}"''[@]}''
[[ $count -lt 1 ]] && return 127
local new_trap
local ref="${stack_name}"''[${#''"${stack_name}"''[@]}-1]''
local cmd=''new_trap=${''"$ref}"; eval $cmd
trap "${new_trap}" "$sig"
eval "unset $ref"
done
}
trap_prepend() {
local new_trap=$1
shift
local sigs=$*
for sig in $sigs; do
if [[ -z $(get_trap $sig) ]]; then
trap_push "$new_trap" "$sig"
else
trap_push "$new_trap ; $(get_trap $sig)" "$sig"
fi
done
}
trap_append() {
local new_trap=$1
shift
local sigs=$*
for sig in $sigs; do
if [[ -z $(get_trap $sig) ]]; then
trap_push "$new_trap" "$sig"
else
trap_push "$(get_trap $sig) ; $new_trap" "$sig"
fi
done
}
Esto puede administrar los controladores que se definen como funciones con nombre y también las rutinas ad-hoc definidas como en este ejemplo, la trap "kill $!" SIGTERM SIGINT
trap "kill $!" SIGTERM SIGINT
.
Este es el script de prueba que utilicé para ayudarme a escribirlo:
#!/bin/bash
source .trap_stack.sh
initial_trap=''echo "messy" ;''" echo ''handler''"
non_f_trap=''echo "non-function trap"''
f_trap() {
echo "function trap"
}
print_status() {
echo " SIGINT trap: `get_trap SIGINT`"
echo " SIGTERM trap: `get_trap SIGTERM`"
echo "-------------"
echo
}
echo "--- TEST START ---"
echo "Initial trap state (should be empty):"
print_status
echo ''Setting messy non-function handler for SIGINT ("original state")''
trap "$initial_trap" SIGINT
print_status
echo ''Pop empty stacks (still in original state)''
trap_pop SIGINT SIGTERM
print_status
echo ''Push non-function handler for SIGINT''
trap_push "$non_f_trap" SIGINT
print_status
echo ''Append function handler for SIGINT and SIGTERM''
trap_append f_trap SIGINT SIGTERM
print_status
echo ''Prepend function handler for SIGINT and SIGTERM''
trap_prepend f_trap SIGINT SIGTERM
print_status
echo ''Push non-function handler for SIGINT and SIGTERM''
trap_push "$non_f_trap" SIGINT SIGTERM
print_status
echo ''Pop both stacks''
trap_pop SIGINT SIGTERM
print_status
echo ''Prepend function handler for SIGINT and SIGTERM''
trap_prepend f_trap SIGINT SIGTERM
print_status
echo ''Pop both stacks thrice''
trap_pop SIGINT SIGTERM
trap_pop SIGINT SIGTERM
trap_pop SIGINT SIGTERM
print_status
echo ''Push non-function handler for SIGTERM''
trap_push "$non_f_trap" SIGTERM
print_status
echo ''Pop handler state for SIGINT (SIGINT is now back to original state)''
trap_pop SIGINT
print_status
echo ''Pop handler state for SIGTERM (SIGTERM is now back to original state)''
trap_pop SIGTERM
print_status