所以我一直遇到一些cli程序的问题。有时当我使用 Ctrl + C 终止正在运行的进程时,它会使终端处于奇怪的状态(例如,关闭回声)。现在,在许多情况下都可以预料到,因为杀死一个进程并没有给它一个机会来恢复终端的状态。但我发现,在许多其他情况下,bash完成是罪魁祸首。例如,请尝试以下操作:
bash --norc
以确保没有加载完成。_completion_test() { grep -q foo /dev/null; return 1; }
。complete -F _completion_test rlwrap
。rlwrap cat
后跟 Tab ,然后输入 Enter 。真正奇怪的是,如果我从完成功能中删除看似无害的grep -q foo /dev/null
,一切都正常。事实上,在我的系统中安装的任何完成功能中添加grep -q foo /dev/null
(甚至更简单的东西,例如cat /dev/null
)会导致同样的问题。我还复制了那些不使用readline
而没有 Ctrl + C 的程序的问题(例如find /var
标签 | head
,上面为find
定义完成。
为什么会这样?
编辑:为了澄清,上面是一个人为的例子。实际上,我想要做的更像是这样:
_completion_test() {
if grep -q "$1" /some/file; then
#do something
else
#do something else
fi
}
有关更具体的示例,请尝试以下操作:
_completion_test() {
if grep -q foo /dev/null; then
COMPREPLY=(cats)
else
return 1
fi
}
但仅仅是我呼叫grep
这一事实导致了问题。在这种情况下,我不明白为什么我无法拨打grep
。
答案 0 :(得分:1)
嗯,答案很简单;这是一个bug:
当可编程完成功能在执行完成功能期间调用外部命令时,会发生这种情况。 Bash在每个成功的作业完成后保存tty状态,因此如果作业被信号杀死并使终端处于不希望的状态,它可以恢复它。在这种情况下,我们需要抑制如果完成的作业在可编程完成期间运行,因为此时的终端设置是readline,它们用于行编辑。此修复程序将在bash-4.4的发行版中。
答案 1 :(得分:-1)
你只是在完成功能的错误实现。请参阅manual
-F功能
shell函数函数在当前shell环境中执行。执行时,$ 1是命令的名称 谁的论点正在完成,2美元是完成的, 如上所述,$ 3是完成单词之前的单词 以上(见可编程完成)。当它完成时,可能 从COMPREPLY数组的值中检索完成 变量
例如以下实现:
_completion_test() { COMPREPLY=($(cat /dev/null)); return 1; }
不会破坏终端。
关于你原来的问题,为什么你的完成功能打破终端,我已经用strace
玩了一点,我看到有ioctl
次-echo
次调用。我假设当您使用 Ctrl + C 终止它时ioctl
echo
参数只是没有被调用以便恢复原始状态。键入stty echo
会返回echo
。