Nomes de servidores de preenchimento automático para SSH e SCP

61

Eu tenho alguns servidores configurados ~/.ssh/config, como alphae beta. Como posso configurar o Bash para que os comandos ssh al<tab>e o scp file.tgz al<tab>preenchimento automático dos nomes dos servidores configurados?

Não quero adicionar os servidores a outro arquivo (ou seja, uma matriz Bash) cada vez que um é adicionado, pois adicionamos e removemos servidores regularmente e a lista é bastante grande.

dotancohen
fonte
2
Você tem o pacote bash-completions instalado para sua distribuição? Eu acho que isso faz parte das rotinas de conclusão padrão, embora eu possa estar confundindo isso com o zsh.
Caleb
Minha instalação faz exatamente isso.
slm
Isso está no Kubuntu 12.10 e eu tenho bash-completioninstalado.
dotancohen

Respostas:

64

Encontrei!!

Parece que no Ubuntu as entradas ~/.ssh/known_hostsestão com hash , então a conclusão do SSH não pode lê-las. Este é um recurso, não um bug. Mesmo adicionando HashKnownHosts noao ~/.ssh/confige /etc/ssh/ssh_configeu era incapaz de impedir o hashing host.

No entanto, os anfitriões em que estou interessado também são encontrados ~/.ssh/config. Aqui está um script para o Bash Completion que lê as entradas desse arquivo:

_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

Coloque esse script /etc/bash_completion.d/sshe origine-o com o seguinte comando:

$ . /etc/bash_completion.d/ssh

Achei este guia inestimável e não seria capaz de escrever isso sem ele. Obrigado Steve Kemp por escrever esse guia fantástico!

dotancohen
fonte
11
Parece que no Centos 6 as entradas em ~ / .ssh / known_hosts substituem as entradas em ~ / .ssh / config, por exemplo. se você tiver foo.bar.baz.com em unknown_hosts, ele corresponderá à coisa toda se você fizer "ssh foo" <tab> - isso é indesejável se você tiver um usuário diferente ou outras configurações que deseja aplicar no ssh confg. Se você possui uma entrada no ssh config que não é preenchida automaticamente corretamente, verifique se ela está presente em known_hosts e exclua-a. Agora deve funcionar normalmente, tirando as configurações do config.
Imran-UK
@ Imran-UK: Sabe-se que o Ubuntu não faz essa coisa sensata, sob o pretexto de segurança. Aparentemente, o pensamento é que uma entidade maliciosa possa, como usuário, editar ~ / .ssh / config, apesar do chmod 0600 no diretório. Ei, não fui eu quem tomou a decisão!
dotancohen
11
Eu uso zsh & oh-my-zsh, acabei de descobrir que ativar o plug-in "ssh" e colocar "HashKnownHosts yes" em meu ~ / .ssh / config parecem fazer a coisa certa. Você pode alterar o shell, independentemente da distribuição, para que possa ser uma maneira de contornar isso.
precisa
@ Imran-UK: Na verdade, eu tentei o zsh no passado e pretendo tentar novamente. Eu vou investigar isso. Shukran meu amigo!
dotancohen
Sei que estou um pouco atrasado para a festa, mas o RHEL 7 completará automaticamente as entradas que estão dentro /etc/hosts, outras distros podem fazer o mesmo.
Centimane
16

Pré-embalado

Você não diz qual distro está usando, mas no meu sistema Fedora 19 eu tenho o seguinte pacote instalado, bash-completionque fornece esse recurso através deste arquivo de regras de conclusão:

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

Aqui está o pacote que eu instalei:

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

Se você examinar esse arquivo de regras, verá estrofes que estão interrogando o $HOME/.ssh/configarquivo:

$ 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"

Rolling your own

Eu também encontrei este Gist, known_hosts_autocomplete.sh , que faz algo semelhante, exceto com o $HOME/.ssh/known_hostsarquivo.

# 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

Você poderia fazer algo semelhante usando seu $HOME/.ssh/configarquivo se, por algum motivo, não conseguir encontrar o arquivo de regras de conclusão para o sshpacote pré-instalado.

slm
fonte
Obrigado. Parece que o Ubuntu não é fornecido com /usr/share/bash-completion/completions/ssh. Você poderia postar o arquivo inteiro em algum lugar onde eu possa copiá-lo? Obrigado!
dotancohen
Você pode obter todos os arquivos deste arquivo: pkgs.fedoraproject.org/repo/pkgs/bash-completion/...
SLM
Sinto muito, mas copiar o arquivo ssh desse arquivo tar para /usr/share/bash-completion/completions/sshnão ajuda! Nem executar o complete -W ...comando no prompt do Bash. Qual pode ser o problema aqui?
dotancohen
Obrigado. Isso parece ser uma decisão de design conhecida no Ubuntu. Portanto, estou aceitando a resposta mesmo que não possa obter a conclusão do bash trabalhando para sshou scp.
dotancohen
2
Homebrew para OSX também tem isso: bash-completion e zsh-completação
Adam Nelson
7

Descobri que o preenchimento automático não estava funcionando porque o Ubuntu faz o hash de hosts conhecidos. Você pode adicionar

Host *
    HashKnownHosts no

Para o seu .ssh/configarquivo, mas os hosts existentes não terão hash.

M1ke
fonte
Obrigado. Na verdade, eu já adicionei essa diretiva ~/.ssh/confige alterei a diretiva /etc/ssh/ssh_confige removi o ~/.ssh/known_hostsarquivo. Após o login nos servidores novamente, os nomes de host ainda estão sendo salvos em hash.
dotancohen
Eu editei minha resposta; você precisará especificar um host e aninhar a diretiva hash dentro; Não listei que muitos .ssh/configarquivos já terão essa linha. Deixe-me saber se isso funciona.
M1ke
Esta é definitivamente a maneira mais fácil de fazer isso! Dado que (versões mais recentes) do Ubuntu agora têm a conclusão ssh ativada, é provavelmente isso que se deseja.
John Montgomery
Como adicionei abaixo, você pode fazer isso, mas provavelmente não deveria - não é necessário para que a conclusão funcione de qualquer maneira. No entanto, se você não concordar e quiser desassistir os hosts existentes depois de adicioná-lo acima, basta rm ~ / .ssh / known_hosts, e isso fará com que seja gerado novamente (sem hash) sempre você faz login em um novo servidor.
Jamieson Becker
3

Para habilitar o autocompletar ssh no Debian e Ubuntu:

sudo apt-get install bash-completion

Observe que isso não tem nada a ver com o hash conhecido_hosts, ao contrário do que foi afirmado acima e da pergunta original. Se você quisesse completar automaticamente a partir de known_hosts, é claro que teria que desativar o hash, mas isso é altamente recomendável.

Por exemplo, eu tenho:

Host *
    HashKnownHosts yes

no meu .ssh / config, e ainda tenho o preenchimento automático do ssh funcionando bem nos hosts listados em .ssh / config e / etc / hosts. Você precisa adicionar o host ao .ssh / config como o OP declarou:

Host my-awesome-host Nome do host the.real.host.name

(Ou você pode adicionar uma entrada de host ao / etc / hosts, que é outra fonte para os scripts Debian / Ubuntu.)

Em seguida, basta digitar ssh my-awe<tab>e ele será concluído automaticamente. Novamente, isso é mesmo se você HashKnownHosts, o que é altamente recomendado. (Observe que a conclusão do bash precisa estar ativada no seu shell do bash, e você precisa especificamente ter esses scripts instalados como acima para sua distribuição.)

Em seguida, adicione essas linhas ao seu .bashrcpara habilitá-lo (requer um logout e login novamente, ou apenas um novo bashdigitado para iniciar um novo shell (você não precisa habilitá-lo se ele já estiver ativado /etc/bash.bashrce nas /etc/profilefontes /etc/bash.bashrc).

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

Isso permitirá autocompletion ssh (entre outras coisas!) De ~/.ssh/config, /etc/hosts, etc.

Note que o Debian assume como padrão ash em vez de bash. Você pode alternar para o bash facilmente:

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

(Você precisará sair e fazer login novamente para que isso entre em vigor.)

Jamieson Becker
fonte
2

No Ubuntu 14.04, sshos servidores são preenchidos automaticamente mencionados no seu~/.ssh/config

Percebi quando percebi que apenas um dos servidores que eu normalmente acessava era preenchido automaticamente. A única diferença entre os dois era uma entrada no arquivo de configuração ssh relacionada à autenticação. Quando adicionei uma nova entrada ao arquivo de configuração para o outro servidor, ele também foi concluído automaticamente.

Aqui está a entrada para aqueles que estavam perguntando:

HOST server-name 
    GSSAPIAuthentication=no

Eu ficaria muito surpreso se isso importasse o que você estava especificando na configuração (desde que ainda seja válido, é claro).

Noé
fonte
Obrigado Noah, o que foi essa entrada? Nos meus sistemas 14.04 e 14.10, o preenchimento automático não funciona.
dotancohen
Não acho que a entrada seja importante - tenho certeza de que ela está apenas lá -, mas adicionarei a entrada à minha resposta.
Noé