Nama server pelengkapan otomatis untuk SSH dan SCP

61

Saya memiliki beberapa server yang dikonfigurasi ~/.ssh/config, seperti alphadan beta. Bagaimana saya bisa mengkonfigurasi Bash sehingga perintah ssh al<tab>dan scp file.tgz al<tab>melengkapi otomatis nama-nama server yang dikonfigurasi?

Saya tidak ingin menambahkan server ke file lain (yaitu array Bash) setiap kali ditambahkan, karena kami menambah dan menghapus server secara teratur dan daftarnya cukup besar.

dotancohen
sumber
2
Apakah Anda memiliki paket bash-completion yang diinstal untuk distro Anda? Saya pikir ini adalah bagian dari rutin penyelesaian standar meskipun saya mungkin bingung dengan zsh.
Caleb
Instal saya melakukan ini.
slm
Ini ada di Kubuntu 12.10, dan saya sudah bash-completionmenginstalnya.
dotancohen

Jawaban:

64

Menemukannya!!

Tampaknya di Ubuntu entri di ~/.ssh/known_hostshash , jadi penyelesaian SSH tidak dapat membacanya. Ini adalah fitur, bukan bug. Bahkan dengan menambahkan HashKnownHosts noke ~/.ssh/configdan /etc/ssh/ssh_configsaya tidak dapat mencegah hashing tuan rumah.

Namun, host yang saya minati juga ditemukan ~/.ssh/config. Berikut ini adalah skrip untuk Bash Completion yang membaca entri dari file itu:

_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

Masukkan skrip itu ke dalam /etc/bash_completion.d/sshdan kemudian sumber dengan perintah berikut:

$ . /etc/bash_completion.d/ssh

Saya menemukan panduan ini sangat berharga dan saya tidak akan bisa menulis tanpa ini. Terima kasih Steve Kemp untuk menulis panduan hebat itu!

dotancohen
sumber
1
Tampaknya dalam entri Centos 6 dalam entri over-ride ~ / .ssh / known_hosts dalam ~ / .ssh / config misalnya. jika Anda memiliki foo.bar.baz.com di known_hosts maka itu akan cocok dengan semuanya jika Anda melakukan "ssh foo" <tab> - ini tidak diinginkan jika Anda memiliki pengguna yang berbeda atau pengaturan lain yang ingin Anda terapkan dari ssh confg. Jika Anda memiliki entri dalam ssh config yang tidak dilengkapi dengan benar secara otomatis, maka periksa apakah ada di known_hosts dan hapus. Sekarang seharusnya berfungsi seperti biasa mengambil pengaturan dari config.
Imran-UK
@ Imran-UK: Diketahui bahwa Ubuntu tidak melakukan hal yang masuk akal, dengan alasan keamanan. Tampaknya pemikirannya adalah bahwa entitas jahat mungkin, sebagai pengguna, mengedit ~ / .ssh / config, meskipun chmod 0600 pada direktori. Hei, bukan aku yang mengambil keputusan!
dotancohen
1
Saya menggunakan zsh & oh-my-zsh, saya baru saja menemukan bahwa mengaktifkan plugin "ssh" dan meletakkan "HashKnownHosts yes" di ~ / .ssh / config saya tampaknya melakukan hal yang benar. Anda dapat mengubah shell apa pun distro sehingga ini mungkin jalan keluarnya.
Imran-UK
@ Imran-UK: Sebenarnya saya sudah mencoba zsh di masa lalu dan saya ingin mencobanya lagi. Saya akan melihat itu. Shukran temanku!
dotancohen
Saya tahu saya sedikit terlambat ke pesta, tetapi RHEL 7 akan melengkapi entri yang ada secara otomatis /etc/hosts, distro lain mungkin melakukan hal yang sama.
Centimane
16

Pra-paket

Anda tidak mengatakan distro apa yang Anda gunakan tetapi pada sistem Fedora 19 saya memiliki paket berikut yang diinstal, bash-completionyang menyediakan fitur ini melalui file aturan penyelesaian ini:

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

Ini paket yang saya instal:

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

Jika Anda melihat file aturan itu Anda akan melihat bait yang menginterogasi $HOME/.ssh/configfile tersebut:

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

Bergulir sendiri

Saya juga menemukan Intisari ini, known_hosts_autocomplete.sh , yang melakukan sesuatu yang serupa kecuali dengan $HOME/.ssh/known_hostsfile.

# 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

Anda dapat melakukan sesuatu yang serupa menggunakan $HOME/.ssh/configfile Anda jika karena alasan tertentu Anda tidak dapat menemukan file aturan penyelesaian untuk yang sshsudah dikemas sebelumnya.

slm
sumber
Terima kasih. Tampaknya Ubuntu tidak disertakan bersama /usr/share/bash-completion/completions/ssh. Bisakah Anda memposting seluruh file di suatu tempat yang mungkin saya salin? Terima kasih!
dotancohen
Anda dapat memperoleh semua file dari arsip ini: pkgs.fedoraproject.org/repo/pkgs/bash-completion/…
slm
Saya minta maaf menjadi sakit, tetapi bahkan menyalin file ssh dari arsip tar /usr/share/bash-completion/completions/sshitu tidak membantu! Tidak menjalankan complete -W ...perintah dari Bash prompt. Apa yang mungkin menjadi masalah di sini?
dotancohen
Terima kasih. Ini sepertinya keputusan desain yang dikenal di Ubuntu. Jadi saya menerima jawabannya meskipun saya tidak dapat menyelesaikan bash untuk sshatau scp.
dotancohen
2
Homebrew untuk OSX juga memiliki ini: bash-completion dan zsh-completions
Adam Nelson
7

Saya menemukan bahwa autocomplete tidak berfungsi karena Ubuntu memiliki host yang dikenal. Anda dapat menambahkan

Host *
    HashKnownHosts no

Ke .ssh/configfile Anda, tetapi host yang ada tidak akan dibatalkan.

M1ke
sumber
Terima kasih. Saya sebenarnya sudah menambahkan arahan ini ke ~/.ssh/configdan mengubah arahan dalam /etc/ssh/ssh_config, dan saya telah menghapus ~/.ssh/known_hostsfile. Setelah masuk ke server lagi, nama host masih disimpan hash.
dotancohen
Saya telah mengedit jawaban saya; Anda perlu menentukan host dan membuat sarang hash directive; Saya tidak menyebutkan bahwa banyak .ssh/configfile sudah memiliki baris ini. Beri tahu saya jika itu berhasil.
M1ke
Ini jelas cara mudah untuk melakukannya! Mengingat bahwa (versi yang lebih baru) Ubuntu sekarang telah mengaktifkan ssh, ini mungkin yang diinginkan.
John Montgomery
Seperti yang saya tambahkan di bawah ini, Anda bisa melakukan ini, tetapi Anda mungkin tidak seharusnya - Anda tidak perlu melakukannya agar tetap bisa berfungsi. Namun, jika Anda tidak setuju dan hanya ingin membatalkan hash dari host yang ada setelah menambahkan itu di atas, Anda bisa saja rm ~ / .ssh / known_hosts, dan itu akan menyebabkannya untuk dihasilkan kembali (tanpa hash) setiap kali Anda masuk ke server baru.
Jamieson Becker
3

Untuk mengaktifkan pelengkapan otomatis ssh di Debian dan Ubuntu:

sudo apt-get install bash-completion

Perhatikan bahwa ini sama sekali tidak ada hubungannya dengan hashing known_hosts, bertentangan dengan apa yang dinyatakan di atas dan pertanyaan awal. Jika Anda ingin melengkapi otomatis dari known_hosts, maka tentu saja Anda harus menonaktifkan hashing, tetapi itu sangat tidak disarankan.

Sebagai contoh, saya punya:

Host *
    HashKnownHosts yes

di .ssh / config saya, dan saya masih memiliki ssh auto-completion yang berfungsi dengan baik terhadap host yang terdaftar di .ssh / config dan / etc / hosts. Anda perlu menambahkan host ke .ssh / config seperti yang dinyatakan OP:

Host my-awesome-host Hostname the.real.host.name

(Atau, Anda dapat menambahkan entri host ke / etc / hosts, yang merupakan sumber lain untuk skrip Debian / Ubuntu.)

Kemudian, Anda bisa mengetik ssh my-awe<tab>dan itu akan selesai secara otomatis. Sekali lagi, ini bahkan jika Anda HashKnownHosts, yang sangat dianjurkan. (Perhatikan bahwa penyelesaian bash perlu diaktifkan di bash shell Anda, dan Anda perlu menginstal skrip-skrip tersebut seperti di atas untuk distribusi Anda.)

Kemudian, tambahkan baris ini ke Anda .bashrcuntuk mengaktifkannya (memerlukan logout dan masuk kembali, atau hanya yang baru bashdiketik untuk meluncurkan shell baru. (Anda tidak perlu mengaktifkan jika sudah diaktifkan /etc/bash.bashrcdan /etc/profilesumber /etc/bash.bashrc).

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

Hal ini akan memungkinkan autocompletion ssh (antara lain!) Dari ~/.ssh/config, /etc/hosts, dll

Perhatikan bahwa Debian default ke ash bukan bash. Anda dapat beralih ke bash dengan mudah:

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

(Anda harus keluar dan masuk kembali agar ini berlaku.)

Jamieson Becker
sumber
2

Di Ubuntu 14,04, pelengkapan sshotomatis server yang disebutkan di Anda~/.ssh/config

Saya perhatikan ketika saya menyadari bahwa hanya satu dari server yang saya akses secara otomatis. Satu-satunya perbedaan antara keduanya adalah entri dalam file konfigurasi ssh yang terkait dengan otentikasi. Ketika saya menambahkan entri baru ke file konfigurasi untuk server lain, itu mulai melengkapi otomatis juga.

Inilah entri untuk mereka yang bertanya:

HOST server-name 
    GSSAPIAuthentication=no

Saya akan sangat terkejut jika itu penting apa yang Anda tentukan dalam konfigurasi (selama itu masih valid, tentu saja).

Nuh
sumber
Terima kasih, Nuh, entri apa itu? Pada sistem autocomplete 14.04 dan 14.10 saya tidak berfungsi.
dotancohen
Saya tidak berpikir entri itu penting - saya cukup yakin itu hanya ada di sana - tetapi saya akan menambahkan entri ke jawaban saya.
Noah