当完成功能读取文件

时间:2016-08-22 03:29:24

标签: linux bash shell bash-completion

所以我一直遇到一些cli程序的问题。有时当我使用 Ctrl + C 终止正在运行的进程时,它会使终端处于奇怪的状态(例如,关闭回声)。现在,在许多情况下都可以预料到,因为杀死一个进程并没有给它一个机会来恢复终端的状态。但我发现,在许多其他情况下,bash完成是罪魁祸首。例如,请尝试以下操作:

  1. 按如下方式开始一个新的bash会话:bash --norc以确保没有加载完成。
  2. 定义完成功能:_completion_test() { grep -q foo /dev/null; return 1; }
  3. 定义使用上述功能的完成:complete -F _completion_test rlwrap
  4. 输入完全以下内容: r l w r a p 空间 c a t Tab < / kbd> 输入(即rlwrap cat后跟 Tab ,然后输入 Enter
  5. 等待一秒,然后使用 Ctrl + C 终止该过程。
  6. 终端的回声应该没有关闭。因此,如果您键入任何字符,它将不会被终端回显。
  7. 真正奇怪的是,如果我从完成功能中删除看似无害的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

2 个答案:

答案 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