arrays bash stack bash-trap

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