SSH和SCP的自动完成服务器名称


61

我在中配置了一些服务器~/.ssh/config,例如alphabeta。我怎么可能配置猛砸这样的命令ssh al<tab>,并scp file.tgz al<tab>自动完成配置的服务器的名称?

我不想每次添加服务器时都将服务器添加到另一个文件(即Bash阵列)中,因为我们会定期添加和删除服务器,并且列表很大。


2
您是否为发行版安装了bash-completions软件包?我认为这是标准完成例程的一部分,尽管我可能会将其与zsh混淆。
Caleb 2014年

我的安装正是这样做的。
slm

这是在Kubuntu 12.10上,并且我已经bash-completion安装了。
dotancohen 2014年

Answers:


64

找到了!!

似乎在Ubuntu中,其中的条目~/.ssh/known_hosts是散列的,因此SSH完成无法读取它们。这是一个功能,而不是错误。即使添加HashKnownHosts no~/.ssh/config/etc/ssh/ssh_config我也无法阻止主机哈希。

但是,在中也找到了我感兴趣的主机~/.ssh/config。这是Bash完成的脚本,该脚本从该文件读取条目:

_ssh() 
{
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    opts=$(grep '^Host' ~/.ssh/config ~/.ssh/config.d/* 2>/dev/null | grep -v '[?*]' | cut -d ' ' -f 2-)

    COMPREPLY=( $(compgen -W "$opts" -- ${cur}) )
    return 0
}
complete -F _ssh ssh

放入该脚本,/etc/bash_completion.d/ssh然后使用以下命令将其来源:

$ . /etc/bash_completion.d/ssh

我发现该指南非常宝贵,没有它,我将无法编写该脚本。感谢Steve Kemp编写了出色的指南!


1
似乎在Centos 6中〜/ .ssh / known_hosts中的条目会覆盖〜/ .ssh / config中的条目,例如。如果您在known_hosts中包含foo.bar.baz.com,那么如果您执行“ ssh foo” <tab>,它将与整个事情相匹配-如果您要从ssh confg应用不同的用户或其他设置,则这是不可取的。如果您在ssh config中有一个无法正确自动完成的条目,则检查它是否存在于known_hosts中并将其删除。现在,它应该可以正常地从config中获取设置。
Imran-UK

@ Imran-UK:众所周知,在安全性的幌子下,Ubuntu并没有做到这一点。显然,这种想法是,尽管目录上的chmod为0600,但恶意实体仍可能以用户身份编辑〜/ .ssh / config。嘿,我不是那个决定的人!
dotancohen

1
我使用zsh和oh-my-zsh,我只是发现在我的〜/ .ssh / config中启用“ ssh”插件并将“ HashKnownHosts yes”放入似乎是正确的事情。您可以更改发行版的shell,这可能是解决它的一种方法。
Imran-UK

@ Imran-UK:实际上,我过去曾经尝试过zsh,并且确实打算再次尝试。我会调查的。我的朋友Shukran!
dotancohen '16

我知道我参加聚会有点晚了,但是RHEL 7会自动完成中的条目/etc/hosts,其他发行版可能会做同样的事情。
Centimane

16

预包装

您没有说要使用什么发行版,但是在Fedora 19系统上,我安装了以下软件包,bash-completion该软件包通过此完成规则文件提供此功能:

/usr/share/bash-completion/completions/ssh

这是我安装的软件包:

$ rpm -aq |grep completion
bash-completion-2.1-2.fc19.noarch

如果查看该规则文件,您将看到正在询问该$HOME/.ssh/config文件的节:

$ grep config /usr/share/bash-completion/completions/ssh
    local configfile
    local -a config
        # Search COMP_WORDS for '-F configfile' or '-Fconfigfile' argument
                    configfile="$(dequote "${1:2}")"
                    [[ $1 ]] && configfile="$(dequote "$1")"
        _known_hosts_real -a -F "$configfile" "$cur"
    local configfile
        # Search COMP_WORDS for '-F configfile' argument
                    configfile="$(dequote "${1:2}")"
                    [[ $1 ]] && configfile="$(dequote "$1")"
        _known_hosts_real -a -F "$configfile" "$cur"
    local configfile prefix
        # Search COMP_WORDS for '-F configfile' or '-Fconfigfile' argument
                    configfile="$(dequote "${1:2}")"
                    [[ $1 ]] && configfile="$(dequote "$1")"
                _known_hosts_real -c -a -F "$configfile" "$cur"

自己滚

我还发现了这个要点,known_hosts_autocomplete.sh,除了$HOME/.ssh/known_hosts文件之外,它执行类似的操作。

# add to ~/.bash_profile, and close/reopen a shell.  Will autocomplete any
# hosts found in known_hosts.

complete -W "$(echo `cat ~/.ssh/known_hosts | cut -f 1 -d ' ' | \
    sed -e s/,.*//g | uniq | grep -v "\["`;)" ssh

$HOME/.ssh/config如果由于某种原因而无法找到ssh已预先打包的完成规则文件,则可以使用文件执行类似的操作。


谢谢。看来Ubuntu没有附带/usr/share/bash-completion/completions/ssh。您可以将整个文件发布到可以复制的位置吗?谢谢!
dotancohen 2014年

您可以从此归档文件中获取所有文件:pkgs.fedoraproject.org/repo/pkgs/bash-completion/…–
slm

对不起,很抱歉,但是即使从该tar存档复制ssh文件/usr/share/bash-completion/completions/ssh也无济于事!complete -W ...从Bash提示符运行命令也不会。这里可能是什么问题?
dotancohen 2014年

谢谢。这似乎确实是Ubuntu中的一个已知设计决策。因此,即使我无法为ssh或进行bash补全,我也接受答案scp
dotancohen 2014年

2
OSX的Homebrew也具有以下功能:bash完成和zsh完成
Adam Nelson

7

我发现自动完成无法正常工作,因为Ubuntu对已知主机进行哈希处理。你可以加

Host *
    HashKnownHosts no

对于您的.ssh/config文件,但现有主机不会被隐藏。


谢谢。实际上,我已经将该指令添加到~/.ssh/config并更改了中的指令/etc/ssh/ssh_config,并且删除了该~/.ssh/known_hosts文件。再次登录服务器后,主机名仍会被散列保存。
dotancohen

我已经编辑了答案;您将需要指定主机,并将hash指令嵌套在其中;我没有列出那么多.ssh/config文件已经包含这一行。让我知道是否可行。
M1ke

这绝对是简单的方法!鉴于(新版本的)Ubuntu现在已启用ssh补全,这可能正是所需要的。
约翰·蒙哥马利

正如我在下面添加的那样,您可以执行此操作,但您可能不应该这样做-无论如何都不需要完成工作。但是,如果您不同意,只是想在添加完上述内容后取消对现有主机的哈希处理,则可以使用rm〜/ .ssh / known_hosts,这将导致它在任何时候重新生成(未哈希)您登录到新服务器。
杰米森·贝克尔

3

要在Debian和Ubuntu中启用ssh自动补全功能:

sudo apt-get install bash-completion

请注意,与上面提到的内容和原始问题相反,这与known_hosts哈希无关。如果要从known_hosts自动完成,则当然必须禁用哈希,但是强烈建议您这样做。

例如,我有:

Host *
    HashKnownHosts yes

在我的.ssh / config中,我仍然可以使用ssh自动补全功能来对.ssh / config和/ etc / hosts中列出的主机正常工作。您确实需要按照OP所述将主机添加到.ssh / config中:

主机my-awesome-host主机名the.real.host.name

(或者,您可以将主机条目添加到/ etc / hosts中,这是Debian / Ubuntu脚本的另一个来源。)

然后,您只需键入ssh my-awe<tab>,它将自动完成。同样,即使您使用HashKnownHosts,也强烈建议这样做。(请注意,需要在bash shell中启用bash补全功能,并且需要专门安装上述脚本以进行分发。)

然后,将这些行添加到您的计算机中.bashrc以启用它(需要注销并重新登录,或者只需bash键入一个新的命令即可启动新的Shell。(如果您已经在/etc/bash.bashrc/etc/profile源中启用了它,则无需启用它/etc/bash.bashrc)。

if [ -f /etc/bash_completion ]; then
    . /etc/bash_completion
fi

这将使SSH自动完成(除其他事项外!)从~/.ssh/config/etc/hosts等等。

请注意,Debian默认为ash而不是bash。您可以轻松切换到bash:

sudo usermod -s /bin/bash "$USER"

(您需要注销并重新登录才能生效。)


2

在Ubuntu 14.04上,ssh自动完成您提到的服务器~/.ssh/config

当我意识到只有我经常访问的一台服务器自动完成时,我注意到了这一点。两者之间的唯一区别是ssh配置文件中与身份验证相关的条目。当我向其他服务器的配置文件中添加新条目时,它也开始自动完成。

这是那些问的人的条目:

HOST server-name 
    GSSAPIAuthentication=no

如果您在配置中指定了什么,我将感到非常惊讶(当然,只要它仍然有效)。


谢谢诺亚,那是什么条目?在我的14.04和14.10系统上,自动完成功能不起作用。
dotancohen 2015年

我认为条目并不重要-我很确定它只是在其中-但是我会将条目添加到我的答案中。
Noah 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.