tcl8.6:内置等效于';atexit()';在stdlib或'中;陷阱“&引用;退出';在bash?

tcl8.6:内置等效于';atexit()';在stdlib或'中;陷阱“&引用;退出';在bash?,tcl,exit,atexit,tclsh,Tcl,Exit,Atexit,Tclsh,我正在寻找一个内置或标准包,它提供的功能与stdlib的atexit()和bash的trap“…”EXIT类似或等效 它应捕获由于任何程序方式结束执行而导致的终止,包括以下所有情况: 自然到达脚本执行的末尾 显式调用exit 未捕获错误 在大多数情况下,拦截此类终止只需拦截exit命令即可 rename exit real\u exit 进程退出参数{ 把“正在退出”的flush stdout;#flush因为我有妄想症。。。 tailcall real_exit{*}$args } 如果显

我正在寻找一个内置或标准包,它提供的功能与stdlib的
atexit()
和bash的
trap“…”EXIT类似或等效

它应捕获由于任何程序方式结束执行而导致的终止,包括以下所有情况:

  • 自然到达脚本执行的末尾
  • 显式调用
    exit
  • 未捕获
    错误
在大多数情况下,拦截此类终止只需拦截
exit
命令即可

rename exit real\u exit
进程退出参数{
把“正在退出”的flush stdout;#flush因为我有妄想症。。。
tailcall real_exit{*}$args
}
如果显式调用它,这显然是可行的,但是如果您只是在交互会话中删除脚本的结尾,发出文件结尾的信号,或者如果您的脚本稍后出现错误并以错误消息终止,那么它也会被调用。这是因为Tcl C API调用,
Tcl_Exit()
,通过调用
Exit
来工作,如果没有退出流程,则直接执行退出本身

注意退出脚本,顺便说一句;其中的错误比正常情况下更难调试



不起作用的案例?主要是在解释器本身无法执行命令的情况下(可能是因为解释器本身已被删除),或者在某些信号关闭解释器的情况下(例如,由于各种原因,默认情况下不处理SIGINT)。

基于@Donal的回答,或多或少完成了
atexit

proc atexit { procbody } {
    if { [catch {set oldbody [info body exit]}] } {
        rename exit builtin_exit
        set oldbody { builtin_exit $returnCode }
    }
    proc exit { {returnCode 0} } [subst -nocommands {
        apply [list [list {returnCode 0}] [list $procbody]] \$returnCode
        tailcall apply [list [list {returnCode 0}] [list $oldbody]] \$returnCode
    }]
}

atexit测试的示例代码.tcl

#!/usr/bin/tclsh8.6

source atexit.tcl

atexit {
    puts "EXITING($returnCode)"; flush stdout; # Flush because I'm paranoid...
}

atexit {
    puts "done($returnCode)..."; flush stdout; # Flush because I'm paranoid...
}

atexit {
    puts "almost($returnCode)..."; flush stdout; # Flush because I'm paranoid...
}

{*}$argv

puts "fell through argv for implicit exit..."
。。。和终端会话:

$ ./atexit-test.tcl 
fell through argv for implicit exit...
almost(0)...
done(0)...
EXITING(0)
$ ./atexit-test.tcl exit
almost(0)...
done(0)...
EXITING(0)
$ ./atexit-test.tcl exit 5
almost(5)...
done(5)...
EXITING(5)
$ ./atexit-test.tcl error "unhandled exception"
unhandled exception
    while executing
"{*}$argv"
    (file "./atexit-test.tcl" line 17)
almost(1)...
done(1)...
EXITING(1)
$ 

这可能很有用:Tcl也有真正的出口处理程序,但它们只在C API级别,因为即使没有解释器可操作,它们也会被调用。谢谢,这很有效。我之前尝试过这种方法,但肯定是犯了一个错误,因为由于
错误
,它无法捕获出口。