Автозаповнення імен серверів для 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, який читає записи з цього файлу:

_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 у відомих_хостях, то це буде відповідати всій справі, якщо ви робите "ssh foo" <tab> - це небажано, якщо у вас є інший користувач або інші налаштування, які ви хочете застосувати з ssh confg. Якщо у вас є запис у ssh config, який не заповнюється автоматично, перевірте, чи він присутній у відомих_хостях, і видаліть його. Тепер він повинен працювати як звичайно, приймаючи налаштування з конфігурації.
Імран-Великобританія

@ Imran-UK: Відомо, що Ubuntu не робить цього розумного, під приводом безпеки. Мабуть, думка полягає в тому, що шкідливий об'єкт може, як користувач, редагувати ~ / .ssh / config, незважаючи на chmod 0600 в каталозі. Гей, я не був тим, хто прийняв рішення!
dotancohen

1
Я використовую zsh & oh-my-zsh, я щойно виявив, що ввімкнення плагіна "ssh" та введення "HashKknownHosts yes" у мій ~ / .ssh / config, здається, робить все правильно. Ви можете змінити оболонку на будь-який дистрибутив, щоб це було можливим шляхом.
Імран-Великобританія

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

Я знаю, що я трохи спізнююся на вечірку, але 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"

Прокат свого

Я також знайшов цей 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/…
slm

Вибачте, що болю, але навіть копіювання файлу ssh з цього архіву tar /usr/share/bash-completion/completions/sshне допоможе! Не виконується виконання complete -W ...команди з підказки Bash. Що може бути тут проблемою?
dotancohen

Дякую. Це здається відомим дизайнерським рішенням в Ubuntu. Таким чином , я приймаю відповідь , навіть якщо я не можу отримати завершення оргії працює sshабо scp.
dotancohen

2
У Homebrew для OSX також є наступне: bash-завершення та zsh-завершення
Adam Nelson

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

Зауважте, що це взагалі не має нічого спільного з хешированием знаних_хостів, всупереч сказаному вище та оригінальному питанню. Якщо ви хотіли автозавершити відомі_hosts, то, звичайно, вам доведеться відключити хешування, але це настійно не рекомендується.

Наприклад, у мене є:

Host *
    HashKnownHosts yes

в моєму .ssh / config, і в мене все ще є автоматичне завершення ssh, яке працює добре проти хостів, перелічених у .ssh / config та / etc / hosts. Вам потрібно додати хост до .ssh / config, як вказано в ОП:

Хост my-awesome-host Hostname the.real.host.name

(Або ви можете додати хост-запис до / etc / hosts, що є ще одним джерелом для сценаріїв Debian / Ubuntu.)

Потім ви можете просто набрати, ssh my-awe<tab>і це буде автоматично виконано. Знову ж таки, це навіть якщо ви HashKknownHosts, що дуже рекомендується. (Зверніть увагу, що завершення 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 за замовчуванням золить замість bash. Ви можете легко перейти на bash:

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

(Вам потрібно буде вийти з системи та увійти знову, щоб це набуло чинності.)


2

У Ubuntu 14.04 sshавтодоповнює сервери, згадані у вашому~/.ssh/config

Я помітив це, коли зрозумів, що лише один із серверів, до яких я часто звертаюся, автоматично завершений. Єдина різниця між ними - це запис у файлі ssh config, який стосувався автентифікації. Коли я додав новий запис у конфігураційний файл для іншого сервера, він також почав автоматично заповнювати.

Ось запис для тих, хто запитував:

HOST server-name 
    GSSAPIAuthentication=no

Я був би дуже здивований, якби це мало значення того, що ви вказували в конфігурації (доки, звичайно, це дійсно).


Дякую, Ной, що це за запис? У моїх системах 14.04 та 14.10 автозаповнення не працює.
dotancohen

Я не думаю, що запис має значення - я впевнений, що це просто їх там, - але я додам запис до своєї відповіді.
Ной
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.