如何自动完成以(涉及别名)sudo 开头的 shell 命令

如何自动完成以(涉及别名)sudo 开头的 shell 命令

假设您的 中具有以下别名.bashrc

alias docker='sudo docker'

然后尝试docker run -v /tmp/test:/foo …在 bash 终端中自动完成,从docker run -v /tmp| → 开始,由于别名中的存在sudo,会出现以下令人分心的行为:

$ docker run -v /tmpTAB
$ docker run -v /tmp[sudo] 用户密码:

Ctrl+C到那时,除了执行和重新启动之外,几乎不可能进一步编辑命令行。

有解决方案来克服这种行为吗?也就是说,保留sudo别名中的隐含内容,但当我们只是期待一些常规的自动完成时,请避免出现密码提示。

独立于该alias功能的解决方案会很好(考虑到直接键入 any 时也会出现此处提出的问题$ sudo command …)。

答案1

如果您想避免 上出现密码提示sudo,请尝试该-n选项。

手册页内容如下sudo

-n, --非交互式

避免提示用户进行任何类型的输入。如果命令运行需要密码,sudo 将显示错误消息并退出。

答案2

依靠 @ApolloXI 的建议sudo -n并进行更多实验,我能够克服我在我的文章中提到的缺点之前的评论

综上所述,自动补全docker …命令时,会加载以下代码:

  • 来自 /etc/bash.bashrc: . /usr/share/bash-completion/bash_completion;
  • 来自 /usr/share/bash-completion/bash_completion:
    • __load_completion docker,
    • 然后. /usr/share/bash-completion/completions/docker;
  • 从 /usr/share/bash-completion/completions/docker :
    • docker version -f '{{.Client.Experimental}} {{.Server.Experimental}} {{.Server.Os}}, ETC。
    • 它重新运行该docker命令(或别名,如果存在)。

所以一个有效的解决方案就是用 bash 函数替换我的别名,检测是否从 bash-completion 功能调用。这可以通过读取数组来完成BASH_SOURCE

因此,我们可以采用以下解决方案:

docker() {
    if [[ "${BASH_SOURCE[*]}" =~ "bash-completion" ]]; then
        sudo -n docker "$@"
    else
        sudo docker "$@"
    fi
}

或者如果我们想要轻松禁用包装器,可以这样写:

__docker() {
    if [[ "${BASH_SOURCE[*]}" =~ "bash-completion" ]]; then
        docker "$@"
    else
        sudo docker "$@"
    fi
}

alias docker=__docker

然后,sudo -n前缀就不再需要了,可以运行例如:

$ \docker run --help

相关内容