保存并恢复陷阱状态?管理陷阱的多个处理程序的简便方法? [英] Save and restore trap state? Easy way to manage multiple handlers for traps?

查看:88
本文介绍了保存并恢复陷阱状态?管理陷阱的多个处理程序的简便方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有什么好方法可以覆盖bash陷阱处理程序,这些处理程序不会永久性破坏可能已设置或尚未设置的现有处理程序?动态管理陷阱例程的任意链怎么办?

What is a good way to override bash trap handlers that don't permanently trample existing ones that may or may not already be set? What about dynamically managing arbitrary chains of trap routines?

有没有一种方法可以保存陷阱处理程序的当前状态,以便以后可以恢复它们?

Is there a way to save the current state of the trap handlers so they can be restored later?

推荐答案

在Bash中保存和还原陷阱处理程序状态

我将提交以下堆栈实现以跟踪和恢复陷阱状态.使用这种方法,我可以推送陷阱更改,然后在完成处理后将其弹出.这也可以用于将许多陷阱例程链接在一起.

Save and Restore Your Trap Handler State in Bash

I would submit the following stack implementation to track and restore trap state. Using this method, I am able to push trap changes and then pop them away when I'm done with them. This could also be used to chain many trap routines together.

请参阅以下源文件(.trap_stack.sh)

See the following source file (.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
}

这可以管理定义为命名函数的处理程序,也可以管理如本例trap "kill $!" SIGTERM SIGINT这样定义的临时例程.

This can manage handlers that are defined as named functions and also ad-hoc routines defined like this example trap "kill $!" SIGTERM SIGINT.

这是我用来帮助我编写的测试脚本:

This is the test script I used to help me write it:

#!/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

这篇关于保存并恢复陷阱状态?管理陷阱的多个处理程序的简便方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆