Автозаполнение имен серверов для SSH и SCP


61

У меня настроено несколько серверов ~/.ssh/config, таких как alphaи beta. Как я могу настроить Bash таким образом, чтобы команды ssh al<tab>и scp file.tgz al<tab>автозаполнять имена настроенных серверов?

Я не хочу добавлять серверы в другой файл (например, массив Bash) каждый раз, когда он добавляется, поскольку мы регулярно добавляем и удаляем серверы, и этот список довольно большой.


2
У вас установлен пакет bash-дополнений для вашего дистрибутива? Я думаю, что это часть стандартных процедур завершения, хотя я мог бы спутать это с zsh.
— Калеб

Моя установка делает именно это.
— SLM

Это на Kubuntu 12.10, и я bash-completionустановил.
— Dotancohen

Ответы:


64

Нашел это !!

Кажется, что в Ubuntu записи в ~/.ssh/known_hostsхэше хэшируются , поэтому SSH-завершение не может их прочитать. Это особенность, а не ошибка. Даже добавив HashKnownHosts noк ~/.ssh/configи /etc/ssh/ssh_configя не смог предотвратить хозяина хэширования.

Тем не менее, хосты, которые меня интересуют, также находятся в ~/.ssh/config. Вот скрипт для Bash Completion, который читает записи из этого файла:

_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

Я нашел это руководство бесценным, и я бы не смог написать это без него. Спасибо Стиву Кемпу за написание этого потрясающего руководства!


1
Похоже, что в Centos 6 записи в ~ / .ssh / known_hosts перезаписывают записи в ~ / .ssh / config, например. если у вас есть foo.bar.baz.com в known_hosts, то он будет полностью соответствовать, если вы выполните «ssh foo» <tab> - это нежелательно, если у вас есть другой пользователь или другие параметры, которые вы хотите применить из ssh confg. Если в конфигурации ssh есть запись, которая не выполняет автозаполнение должным образом, проверьте, присутствует ли она в known_hosts, и удалите ее. Теперь он должен работать как обычно, принимая настройки из конфига.
— Имран, Великобритания,

@ Imran-UK: Известно, что Ubuntu не делает этого разумного, под предлогом безопасности. Очевидно, мысль заключается в том, что злонамеренный объект может, как пользователь, редактировать ~ / .ssh / config, несмотря на chmod 0600 в каталоге. Эй, я не тот, кто принял решение!
— dotancohen

1
Я использую zsh & oh-my-zsh, я только что обнаружил, что включение плагина "ssh" и добавление "HashKnownHosts yes" в моем ~ / .ssh / config, кажется, делает правильно. Вы можете изменить оболочку в любом дистрибутиве, так что это может быть обходным путем.
— Имран, Великобритания,

@ Imran-UK: На самом деле я пробовал zsh в прошлом и собираюсь попробовать снова. Я посмотрю на это. Шукран мой друг!
— dotancohen

Я знаю, что немного опоздал на вечеринку, но RHEL 7 будет автоматически заполнять записи, которые есть в /etc/hostsдругих дистрибутивах.
— Сентиман

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"

Роллинг свой собственный

Я также нашел этот Gist, 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

Вы можете получить все файлы из этого архива: pkgs.fedoraproject.org/repo/pkgs/bash-completion/...
— ОДС

Извините за боль, но даже копирование файла ssh из этого архива tar /usr/share/bash-completion/completions/sshне помогает! Также не выполняется complete -W ...команда из командной строки Bash. В чем может быть проблема здесь?
— dotancohen

Спасибо. Похоже, это известное дизайнерское решение в Ubuntu. Таким образом, я принимаю ответ, несмотря на то, что не могу получить завершение bash для sshили scp.
— dotancohen

2
Homebrew для OSX также имеет следующее: завершение bash и завершение zsh
— Адам Нельсон

7

Я обнаружил, что автозаполнение не работает, потому что Ubuntu хеширует известные хосты. Можете добавить

Host *
    HashKnownHosts no

К вашему .ssh/configфайлу, но существующие хосты не будут хэшированы.


Спасибо. Я фактически уже добавил эту директиву ~/.ssh/configи изменил ее /etc/ssh/ssh_config, и я удалил ~/.ssh/known_hostsфайл. После повторного входа на серверы имена хостов все еще сохраняются в хэше.
— dotancohen

Я отредактировал свой ответ; вам нужно будет указать хост и вложить в него директиву хеша; Я не перечислял, что у многих .ssh/configфайлов уже будет эта строка. Дай мне знать, если это работает.
— M1ke

Это определенно простой способ сделать это! Учитывая, что (в более новых версиях) Ubuntu теперь включено завершение ssh, это, вероятно, то, что нужно.
— Джон Монтгомери

Как я добавил ниже, вы можете сделать это, но вы, вероятно, не должны - вам не нужно, чтобы завершить работу в любом случае. Однако, если вы не согласны и просто хотите отменить хэширование существующих хостов после добавления вышеупомянутого, вы можете просто выполнить команду rm ~ / .ssh / known_hosts, и это приведет к ее повторной генерации (без хэширования) всякий раз, когда Вы входите в новый сервер.
— Джеймисон Беккер

3

Чтобы включить автозаполнение ssh в Debian и Ubuntu:

sudo apt-get install bash-completion

Обратите внимание, что это не имеет ничего общего с хэшированием known_hosts, в отличие от того, что было сказано выше и исходного вопроса. Если вы хотите выполнить автозаполнение с known_hosts, то, конечно, вам придется отключить хеширование, но это настоятельно рекомендуется.

Например, у меня есть:

Host *
    HashKnownHosts yes

в моем .ssh / config, и у меня все еще есть автоматическое завершение ssh, работающее с хостами, перечисленными в .ssh / config и / etc / hosts. Вам нужно добавить хост в .ssh / config, как указано в OP:

Host my-awesome-host Имя хоста the.real.host.name

(Или вы можете добавить запись хоста в / etc / hosts, который является другим источником для сценариев Debian / Ubuntu.)

Затем вы можете просто напечатать, ssh my-awe<tab>и это будет автоматически завершено. Опять же, это даже если вы HashKnownHosts, что настоятельно рекомендуется. (Обратите внимание, что завершение bash должно быть включено в вашей оболочке bash, и вам необходимо специально установить эти сценарии, как указано выше для вашего дистрибутива.)

Затем добавьте эти строки в свой, .bashrcчтобы включить его (требуется выйти из системы и снова войти в систему, или просто bashввести новый текст для запуска новой оболочки. (Вам не нужно включать, если он уже включен /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

Я не думаю, что запись имеет значение - я почти уверен, что они там есть - но я добавлю эту запись в свой ответ.
— Ноа
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.