#!/bin/bash # # Usage: # # finally [args...] # # What it does: # # (1) First, the is executed with its arguments if any. # # (2) Then is executed as it would be by eval in # the most global scope of the shell. (It is actually sent to # the bash prompt's standard input as a list of quoted words.) # # Reason to exist: # # If execution of is interrupted by signal, the # will still run. finally() { exec \ {FINALLY_0}<&0 \ {FINALLY_1}>&1 \ {FINALLY_2}>&2 \ 0< <(finally_unwind "$1") \ &> /dev/null # silence prompt # note that finally_unwind still has un-redirected # stdin/stderr { "${@:2}" } <&$FINALLY_0 >&$FINALLY_1 2>&$FINALLY_2 } finally_unwind() { case $# in 0 ) exec \ 0<&$FINALLY_0 \ 1>&$FINALLY_1 \ 2>&$FINALLY_2 \ {FINALLY_0}<&- \ {FINALLY_1}>&- \ {FINALLY_2}>&- ;; 1 ) echo "history -d -1; finally_unwind; $1" ;; esac }