退出钩子适用于 Bash 和 ZSH

Luc*_*aio 5 bash shell zsh

我需要创建一个脚本,它基本上设置一些环境变量,启动一个子 shell,并在退出时运行一些附加代码,作为钩子。它需要同时在 Bash 和 ZSH 上运行,我知道也许我应该维护两个不同的脚本。

我需要它的原因是创建某种引导脚本。例如,我创建了一个名为Bootstrap.sh的文件,其中包含两个函数startexit,当我运行脚本时,start应该调用 和 ,并激活一个新的子 shell。当子 shell 退出时,exit最终会调用 , 。例如:

# Bootstrap.sh
start() {
    export CUSTOM_VAR="hello world"
}

exit() {
    echo "byebye"
}
Run Code Online (Sandbox Code Playgroud)

$ bootstrap
$ # 找到“Bootstrap.sh”,加载它,然后调用“start”函数
(myenv) $ echo $CUSTOM_VAR
hello world
(myenv) $ exit
byebye # 这是我的退出钩子
$ # 回到“正常”shell

我正在使用这个脚本测试钩子,基于改进 Python 的virtualenv的建议。在此文件中,我尝试使用 trap (a) 和 TRAPEXIT(b),但这些都不起作用:

# (a), the "bash way", I think
my_hook() {
    echo "exit hook called"
}
trap my_hook EXIT
exec "${@:-$SHELL}"
Run Code Online (Sandbox Code Playgroud)
# (b), as explained in ZSH documentation
# http://zsh.sourceforge.net/Doc/Release/Functions.html
TRAPEXIT() {
    echo "exit hook called"
}
exec "${@:-$SHELL}"
Run Code Online (Sandbox Code Playgroud)

那么,我该怎么做(如果可能的话,在 ZSH 和 Bash 中)?

Ant*_*ala 5

根据 ZSH 手册页,ZSH 还支持内置trap;那是,

trap 'any code here' EXIT
Run Code Online (Sandbox Code Playgroud)

也适用于 ZSH,并且您可以将函数名称作为代码字符串。

如果您需要包装 exec,以下内容应该适用于 bash 和 zsh

function exec {
    echo "Execcing"
    builtin exec "$@"
}
Run Code Online (Sandbox Code Playgroud)


M.E*_*.L. 1

问题是最后的“exec”。这(显然)不算是退出。当然,替换的进程不会继承 shell 的退出处理程序。

解决方案:更换

exec "${@:-$SHELL}"
Run Code Online (Sandbox Code Playgroud)

经过

"${@:-$SHELL}"
Run Code Online (Sandbox Code Playgroud)

PS:我说显然,因为我从来没有想过它是否会(算作退出,我的意思是)。我不得不尝试一下,但按理说,exec 与退出无关。该进程仅在“{@:-$SHELL}”终止时退出。