Zsh üzerinde ssh için komut tamamlama nasıl düzenlenir?


11

Ben yazdıktan sonra ana bilgisayar adlarını görüntülemek için zsh üzerinde komut tamamlama ayarlamak istiyorum

ssh [TAB]

adları .ssh / config dosyamdan (ve tercihen bilinen_anahtarlar ve / etc / hosts ve mantıklı olan herhangi bir yerden) almak ve tek bir liste sunmak.

Şu anda bunlardan bazılarını yapıyor, ancak

  1. hiç .ssh / config kullanmaz
  2. .ssh / config kullanmak kullanıcı adlarını yazmayı gereksiz kılsa da, önce bir kullanıcı adı gerektirir
  3. birden fazla liste sunar (muhtemelen biri bilinen_hosts ve diğeri / etc / hosts, ancak bunu doğrulamadım)

Bu nedenle, ssh [TAB] yazdıktan sonra (tercihen tekli) listeye bilinen kullanıcı adlarının yanı sıra bilinen ana bilgisayar adlarını dahil etmek istiyorum

(Buraya Google'dan önce geliyorum çünkü 1) cevabın burada saklanmasıyla sonuçlanacak ve 2) muhtemelen daha etkilidir. Başka kimse cevap vermezse, cevabı avlayacağım.)


Bence bu süper kullanıcı için bir soru olurdu
Etienne Perot

Aslında, şimdi bakarak unix.stackexchange.com üzerinde sormalıydım. (Ama bunu sorduğumda yaklaşık 2 yıl önce olup olmadığını hatırlamıyorum.) Göç etmek isteyen var mı?
iconoclast

Yanıtlar:


16

İşte benim ilgili bölüm .zshrc. 2002'den bu yana değişmedi, bu yüzden bugün farklı yazabilirim, ancak hala ~/.ssh/configve ana bilgisayar adlarını ~/.ssh/known_hosts(eğer HashKnownHostskapalı ise - o günlerde yoktu) tamamlamak için hala çalışıyor .

h=()
if [[ -r ~/.ssh/config ]]; then
  h=($h ${${${(@M)${(f)"$(cat ~/.ssh/config)"}:#Host *}#Host }:#*[*?]*})
fi
if [[ -r ~/.ssh/known_hosts ]]; then
  h=($h ${${${(f)"$(cat ~/.ssh/known_hosts{,2} || true)"}%%\ *}%%,*}) 2>/dev/null
fi
if [[ $#h -gt 0 ]]; then
  zstyle ':completion:*:ssh:*' hosts $h
  zstyle ':completion:*:slogin:*' hosts $h
fi

Tamam, sonunda bunun neden işe yaramadığını anladım. Sorun sağladığınız kodla ilgili değildi: diğer sorun çözüldükten sonra iyi çalışıyor.
iconoclast

1

sshTamamlama sağlayan işlev /usr/share/zsh/functions/Completion/Unix/_sshsistemimde bulunur.

Ayrıca man zshcompsysbelgelere bakın (özellikle birden fazla yerde görünen "ana bilgisayar" ve birkaç yerde görünen "ssh" araması yapın).

Bir zstylekomut eklemenin ~/.zshrctamamlama işlevini değiştirmek zorunda kalmadan aradığınızı yapması mümkün olabilir .


Veya /usr/share/zsh/4.3.9/functions/_sshMac OS X'te (sürümü uyarlayın)
Studer

Ben bu dosyayı kaynak ve ssh <TAB> yazın ve dosya adı tamamlama olsun. Buna ne dersin?
iconoclast

1

Bunu dig kullanarak belirli bir etki alanındaki tüm ana bilgisayarların listesini kullanarak yaparım. Aşağıdaki işlevi, hosts dosyanız veya statik bir liste de dahil olmak üzere istediğiniz arama sistemi ile değiştirebilirsiniz:

function complete_host_from_zone () {
    reply=(`dig axfr ouraynet.com @ns1.ouraynet.com | grep -e '^[a-z]' | cut -d\. -f1`)
}
compctl -x 'p[1]' -K complete_host_from_zone -- ssh

Not: Yukarıdaki kod, yapılandırmanızdaki ssh komutu için sistemin tamamını değiştirmeyebilir. Sorun yaşarsanız, "ssh" komutunu "mycompletetest" gibi başka bir rastgele komutla değiştirmeyi deneyin ve tamamlamanın bunun için işe yarayıp yaramadığını görün.

Ayrıca, bunun her tamamlamada dns bölgesi aktarımını yaptığını da unutmayın! Bunu çok ya da oldukça statik bir alanda kullanırsanız, aramayı yapmak ve sonucu kaydetmek mantıklı olacaktır, o zaman arama işlevinizde answer = zone_result ayarını yapın.


Hiç çalışamıyorum. Açıkçası cevap bölümünü değiştirmek zorundayım, ancak statik metinle çalışan bir örnek verebilir misiniz, bu yüzden hangi formatta olması gerektiğini biliyorum? (Adam sayfasını anlamaya çalıştığım şeyi denedim ve -k'yi -K'ya düzelttim ve hala işe yaramadı.)
iconoclast

Cevap formatı oldukça basit, sadece düz bir metin bloğu, her satırda bir olası cevap. Dns şey muhtemelen zor kısmıdır. Bunun için DNS sunucunuzun bölge aktarımını desteklemesi gerekir. Bu genellikle söz konusu alan adı için birincil dns sunucusuyla konuşmanız gerektiği anlamına gelir dig axfr mydomain.com @ns1.mydomain.com. Bunu manuel olarak çalıştırabildiğinizden ve çıktının bir kısmının söz konusu etki alanında kayıtlı olan ana bilgisayarların listesi ve bunların A veya her hangi bir kayıt olması gerektiğinden emin olun. Ben de bunun için uğraşıyordum, daha sonra tam nitelikli kaydı değil, sadece hostname kısmını kestim.
Caleb

Bölge aktarım aramasının çalıştığı bir etki alanı adı da dahil olmak üzere tam olarak çalışan kesme ve yapıştırma çözümü olmak için cevabımda örnek kodu yeniden yazdığınızı lütfen unutmayın. Daha sonra süit için terzi yapabilirsiniz. Bu örnekle ilgili olmayan .zshrc dosyamda bulunan yaklaşık 20 ekstra katmanı söktüğümde iki yazım hatasıyla sonuçlanan orijinal için özür dilerim.
Caleb

Backticks'teki dig komutu şimdi çalışıyor (düzenlediğiniz için teşekkürler!), Ancak ssh <TAB> yazdığımda bu komutun sonuçlarından hiçbirini göstermiyor. Bunun dışında, çalışması için etkinleştirilmesi gereken başka bir şey var mı?
iconoclast

0

Karma dosyamı tutmayı seviyorum known_hostsve kapatmak istemiyorum HashKnownHosts. @Gilles'ın geçmişimde olanlarla tohumlama ihtiyacımın oldukça etkili olduğunu keşfettim.

h=($(echo $(history | awk '{print $4 " " $5 "\n"}' | grep 'ssh ' | awk '{print $2}' | sort -u)))
if [[ -r ~/.ssh/config ]]; then
  h=($h ${${${(@M)${(f)"$(cat ~/.ssh/config)"}:#Host *}#Host }:#*[*?]*})
fi
if [[ -r ~/.ssh/known_hosts ]]; then
   h=($h ${${${(f)"$(cat ~/.ssh/known_hosts{,2} || true)"}%%\ *}%%,*}) 2>/dev/null
fi
if [[ $#h -gt 0 ]]; then
  zstyle ':completion:*:ssh:*' hosts $h
  zstyle ':completion:*:slogin:*' hosts $h
fi

Ayrıca, FWIW, Bash için kullandığım şey bu:

# SSH Autocompletion
complete -W "
  $(echo $(grep '^\s*ssh ' ~/.bash_history | sort -u | sed 's/^ssh //' | awk '{print $1}'))
  $(echo $(history | awk '{print $2 " " $3}' | grep 'ssh ' | awk '{print $2}' | sort -u))
  $(sed 's/#.*//;' ~/.ssh/config | awk ' /^Host (.+)$/ {$1 = "";print tolower($0)}')
" ssh
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.