我经常使用 Ctrl-D 退出交互式 Python 会话,但有时我会在 Python 会话未开启时意外按下它。这将导致向 shell 发送 EOF 并随后关闭它(而不要求确认)。我通过谷歌搜索找到了两个解决方案:
set -o ignoreeof
export IGNOREEOF=10
第一个选项在我的 zsh shell 和 bash shell 中运行良好。但是,第二个选项似乎只在 bash 中有效。当我在 zsh 中时,无论我为 设定了什么数字IGNOREEOF
,它都会发送 EOF,就像没有设定一样。
有人能帮我解释一下为什么 ZSH 会这样做吗?或者这只是我的 zsh shell 中某些特殊的环境设置造成的?
答案1
Zsh 不像 Bash 那样使用IGNOREEOF
参数。相反,它是一个必须通过setopt
内置命令设置的选项。来自zshoptions(1)
:
忽略 EOF (-7)
文件结束时不退出。要求使用 exit 或 logout。 但是,连续十次 EOF 都会导致 shell 退出,以避免当 tty 消失时 shell 挂起。
此外,如果设置了此选项并使用 Zsh 行编辑器,则由 shell 函数实现的小部件可以绑定到 EOF(通常是 Control-D),而不会打印正常的警告消息。这仅适用于普通小部件,不适用于完成小部件。
--如果你想模拟 Bash 的 IGNOREEOF,第二段很重要;见下文
您可以通过将以下内容添加到 shell 配置来启用此选项:
setopt ignore_eof # Option names are case-insensitive and underscores are optional.
模拟 Bash(可选)
如果你想模拟 Bash 的行为,能够在退出 shell 之前指定Ctrl+序列的数量,那么你可以添加以下内容DZLE 小部件定义* 您的配置:
# Emulate Bash $IGNOREEOF behavior
bash-ctrl-d() {
if [[ $CURSOR == 0 && -z $BUFFER ]]
then
[[ -z $IGNOREEOF || $IGNOREEOF == 0 ]] && exit
if [[ $LASTWIDGET == bash-ctrl-d ]]
then
(( --__BASH_IGNORE_EOF <= 0 )) && exit
else
(( __BASH_IGNORE_EOF = IGNOREEOF-1 ))
fi
zle send-break
else
zle delete-char-or-list
fi
}
然后,将小部件添加到 ZLE 并为其创建一个键绑定:
zle -N bash-ctrl-d
bindkey '^D' bash-ctrl-d
您仍然需要设置ignore_eof
选项但是,否则Ctrl+D将忽略 ZLE 并立即退出 shell,而不管此小部件如何。请参阅答案开头的手册页片段的第二段。
* - 此小部件的原作者为 Christoph Lange,Bart Schaefer 对此进行了修改
答案2
我发现了:
zle send-break
和
zle delete-char-or-list
导致 LASTWIDGET 始终为 zle-line-init,而不是 bash-ctrl-d,因此 shell 永远不会结束。我必须删除这些行才能使 __BASH_IGNORE_EOF 递减。例如:
# 2x ctrl-d to exit ...
export IGNOREEOF=1
# bash like ctrl-d wrapper for IGNOREEOF
setopt ignore_eof
function bash-ctrl-d() {
if [[ $CURSOR == 0 && -z $BUFFER ]]
then
[[ -z $IGNOREEOF || $IGNOREEOF == 0 ]] && exit
if [[ "$LASTWIDGET" == "bash-ctrl-d" ]]
then
(( --__BASH_IGNORE_EOF <= 0 )) && exit
else
(( __BASH_IGNORE_EOF = IGNOREEOF ))
fi
fi
}
zle -N bash-ctrl-d
bindkey "^d" bash-ctrl-d
我正在使用 zsh 5.1.1。谢谢,-m