วิธีแก้ไขคำสั่งเสร็จสิ้นสำหรับ ssh บน zsh?


11

ฉันต้องการตั้งค่าความสมบูรณ์ของคำสั่งใน zsh เพื่อแสดงชื่อโฮสต์หลังจากที่ฉันพิมพ์

ssh [TAB]

นำชื่อออกจากไฟล์. ssh / config ของฉัน (และควรเป็นที่รู้จักจาก known_hosts และ / etc / hosts และอื่น ๆ ที่เหมาะสม) และนำเสนอรายการเดียว

มันทำอะไรบางอย่างในขณะนี้ แต่

  1. มันไม่ได้ใช้. ssh / config เลย
  2. ต้องการชื่อผู้ใช้ก่อนแม้ว่าการใช้. ssh / config จะทำให้การพิมพ์ชื่อผู้ใช้ไม่จำเป็น
  3. มันมีหลายรายการ (อาจเป็นหนึ่งใน known_hosts และอีกรายการจาก / etc / hosts แต่ฉันยังไม่ได้ยืนยัน)

ดังนั้นฉันจึงต้องการที่จะรวมชื่อผู้ใช้ที่รู้จักและชื่อโฮสต์ที่รู้จักในรายการ (ดีกว่าเดียว) หลังจากพิมพ์ ssh [TAB]

(ฉันมาที่นี่ก่อน Google เพราะ 1) มันจะส่งผลให้คำตอบถูกเก็บไว้ที่นี่และ 2) อาจมีประสิทธิภาพมากกว่า หากไม่มีใครตอบฉันจะตามหาคำตอบ)


นี่จะเป็นคำถามสำหรับ superuser ฉันคิดว่า
Etienne Perot

ที่จริงแล้วการดูมันตอนนี้ฉันควรจะถามมันใน unix.stackexchange.com (แต่ฉันจำไม่ได้ว่าเป็นเมื่อประมาณ 2 ปีที่แล้วเมื่อฉันถาม) ทุกคนต้องการย้ายข้อมูลหรือไม่
iconoclast

คำตอบ:


16

.zshrcนี่คือส่วนที่เกี่ยวข้องจากฉัน มันไม่ได้เปลี่ยนไปตั้งแต่ปี 2002 ดังนั้นฉันอาจจะเขียนมันแตกต่างกันในวันนี้ แต่ก็ยังคงใช้งานได้กับชื่อโฮสต์ที่สมบูรณ์จาก~/.ssh/configและ~/.ssh/known_hosts(ถ้าHashKnownHostsปิด - มันไม่ได้มีอยู่ในสมัยนั้น)

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

โอเคฉันคิดในท้ายที่สุดว่าทำไมมันถึงไม่ทำงาน ปัญหาไม่ได้อยู่กับรหัสที่คุณระบุ: ใช้งานได้ดีเมื่อปัญหาอื่น ๆ ได้รับการแก้ไข
iconoclast

1

ฟังก์ชั่นที่ให้การsshเติมเต็มจะอยู่ที่/usr/share/zsh/functions/Completion/Unix/_sshระบบของฉัน

ดูman zshcompsysเอกสารประกอบ (โดยเฉพาะทำการค้นหาใน "โฮสต์" ซึ่งปรากฏในหลาย ๆ ที่และ "ssh" ซึ่งปรากฏในสองแห่ง)

อาจเป็นไปได้ว่าการเพิ่มzstyleคำสั่งลงใน~/.zshrcสิ่งที่คุณต้องการโดยไม่ต้องแก้ไขฟังก์ชั่นการเติมให้สมบูรณ์


หรือใน/usr/share/zsh/4.3.9/functions/_sshMac OS X (ปรับรุ่น)
Studer

ฉันแหล่งที่มาของไฟล์นั้นและพิมพ์ ssh <TAB> และฉันจะได้รับชื่อไฟล์ที่สมบูรณ์ เกิดอะไรขึ้นกับสิ่งนั้น
iconoclast

1

ฉันทำสิ่งนี้โดยใช้รายการโฮสต์ทั้งหมดในโดเมนที่กำหนดโดยใช้ dig คุณสามารถแทนที่ฟังก์ชั่นด้านล่างด้วยระบบค้นหาใด ๆ ที่คุณต้องการรวมถึงไฟล์โฮสต์หรือรายการคงที่:

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

หมายเหตุ:รหัสด้านบนอาจไม่สามารถแทนที่ระบบที่สมบูรณ์สำหรับคำสั่ง ssh ในการกำหนดค่าของคุณ หากคุณมีปัญหาลองเปลี่ยนคำสั่ง "ssh" เป็นคำสั่งแบบสุ่มอื่น ๆ เช่น "mycompletetest" และดูว่าการทำงานให้เสร็จสมบูรณ์นั้นหรือไม่

นอกจากนี้โปรดทราบว่านี่เป็นการถ่ายโอนโซน dns ในทุก ๆ การสำเร็จ หากคุณใช้โดเมนจำนวนมากหรือโดเมนแบบคงที่คุณควรทำการค้นหาและบันทึกผลลัพธ์จากนั้นในฟังก์ชั่นการค้นหาของคุณให้ตั้งค่า reply = zone_result


ฉันไม่สามารถทำงานได้เลย เห็นได้ชัดว่าฉันต้องเปลี่ยนส่วนตอบกลับ แต่คุณสามารถให้ตัวอย่างการทำงานกับข้อความแบบคงที่ดังนั้นฉันรู้ว่ารูปแบบที่ควรจะอยู่ใน? (ฉันลองในสิ่งที่ฉันเข้าใจหน้าคนจะพูดและแก้ไข -k ถึง -K และมันก็ยังใช้งานไม่ได้)
iconoclast

รูปแบบการตอบกลับค่อนข้างง่ายมันเป็นเพียงหยดข้อความที่ตรงหนึ่งคำตอบที่เป็นไปได้ต่อบรรทัด สิ่งที่ DNS น่าจะเป็นส่วนที่ยุ่งยาก เซิร์ฟเวอร์ DNS ของคุณต้องรองรับการถ่ายโอนโซนเพื่อให้สิ่งนี้ทำงานได้ นี้มักจะหมายความว่าคุณจะต้องมีการพูดคุยกับเซิร์ฟเวอร์ DNS dig axfr mydomain.com @ns1.mydomain.comหลักสำหรับโดเมนในคำถามเช่นนี้ ตรวจสอบให้แน่ใจว่าคุณสามารถเรียกใช้ด้วยตนเองและส่วนหนึ่งของผลลัพธ์ควรเป็นรายการของโฮสต์ที่ลงทะเบียนในโดเมนนั้นและ A หรือระเบียนใด ๆ ของพวกเขา นั่นคือสิ่งที่ฉันกำลัง greping แล้วตัดเฉพาะชื่อโฮสต์ส่วนที่ไม่ครบถ้วนบันทึก
Caleb

Pleasenote ที่ฉันได้เขียนโค้ดตัวอย่างใหม่ในคำตอบของฉันเพื่อให้การแก้ปัญหาการตัดและวางทำงานได้อย่างสมบูรณ์รวมถึงชื่อโดเมนที่การค้นหาการถ่ายโอนโซนทำงาน จากนั้นคุณสามารถปรับแต่งชุด ฉันขอโทษสำหรับต้นฉบับที่จบลงด้วยการพิมพ์ผิดสองครั้งจากเมื่อฉันคัดลอกสิ่งเพิ่มเติมอีกประมาณ 20 เลเยอร์ที่อยู่ในไฟล์. zshrc ของฉันที่ไม่เกี่ยวข้องกับตัวอย่างนี้
Caleb

คำสั่ง dig ใน backticks ใช้งานได้ในขณะนี้ (ขอบคุณสำหรับการแก้ไข!) แต่มันไม่แสดงผลลัพธ์ของคำสั่งนั้นเมื่อฉันพิมพ์ ssh <TAB> มีอะไรอีกบ้างนอกเหนือจากนี้ที่ต้องเปิดใช้งานก่อนที่จะใช้งานได้
iconoclast

0

ฉันชอบเก็บknown_hostsไฟล์แฮชของฉันและไม่ต้องการHashKnownHostsปิด ฉันพบว่าการสร้างสิ่งที่ @Gilles มีกับสิ่งที่มีอยู่แล้วในประวัติศาสตร์ของฉันนั้นค่อนข้างมีประสิทธิภาพสำหรับความต้องการของฉัน

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

นอกจากนี้ FWIW นี่คือสิ่งที่ฉันใช้สำหรับ Bash:

# 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.