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

61

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

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

dotancohen
источник
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

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

dotancohen
источник
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уже предварительно упакованного.

SLM
источник
Спасибо. Кажется, что 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файлу, но существующие хосты не будут хэшированы.

M1ke
источник
Спасибо. Я фактически уже добавил эту директиву ~/.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
Я не думаю, что запись имеет значение - я почти уверен, что они там есть - но я добавлю эту запись в свой ответ.
Ноа