Làm cách nào để chỉnh sửa hoàn thành lệnh cho ssh trên zsh?


11

Tôi muốn thiết lập hoàn thành lệnh trên zsh để hiển thị tên máy chủ sau khi tôi nhập

ssh [TAB]

lấy tên ra khỏi tệp .ssh / config của tôi (và tốt nhất là từ know_hosts và / etc / hosts và bất kỳ nơi nào khác có ý nghĩa) và trình bày một danh sách duy nhất.

Nó hiện một số điều này, nhưng

  1. nó hoàn toàn không sử dụng .ssh / config
  2. nó yêu cầu tên người dùng trước, mặc dù việc sử dụng .ssh / config khiến việc nhập tên người dùng không cần thiết
  3. nó trình bày nhiều danh sách (có thể là một danh sách từ know_hosts và một danh sách khác từ / etc / hosts, nhưng tôi chưa xác minh điều đó)

Vì vậy, tôi muốn đưa tên người dùng đã biết cũng như tên máy chủ đã biết vào danh sách (tốt nhất là đơn) sau khi nhập ssh [TAB]

(Tôi đến đây trước Google vì 1) nó sẽ dẫn đến câu trả lời được lưu trữ ở đây và 2) nó có thể hiệu quả hơn. Nếu không có ai trả lời, tôi sẽ săn lùng câu trả lời.)


Đây sẽ là một câu hỏi cho siêu người dùng, tôi nghĩ
Etienne Perot

Trên thực tế, nhìn vào nó bây giờ tôi nên hỏi nó trên unix.stackexchange.com. (Nhưng tôi không nhớ nếu đó là khoảng 2 năm trước khi tôi hỏi nó.) Có ai muốn di chuyển nó không?
iconoclast

Câu trả lời:


16

Đây là phần có liên quan từ tôi .zshrc. Nó đã không thay đổi kể từ năm 2002, vì vậy tôi có thể viết nó khác ngày hôm nay, nhưng nó vẫn hoạt động để hoàn thành tên máy chủ từ ~/.ssh/config~/.ssh/known_hosts(nếu HashKnownHostsbị tắt - nó không tồn tại trong những ngày đó).

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

Được rồi, cuối cùng tôi đã tìm ra lý do tại sao điều này không hoạt động. Vấn đề không nằm ở mã bạn cung cấp: nó hoạt động tốt, một khi vấn đề khác được giải quyết.
iconoclast

1

Chức năng cung cấp sshhoàn thành được đặt tại /usr/share/zsh/functions/Completion/Unix/_sshhệ thống của tôi.

Cũng xem man zshcompsystài liệu (đặc biệt là tìm kiếm trên "máy chủ" xuất hiện ở nhiều nơi và "ssh" xuất hiện ở một vài nơi).

Có thể việc thêm một zstylelệnh vào ~/.zshrcsẽ làm những gì bạn đang tìm kiếm mà không phải sửa đổi chức năng hoàn thành.


Hoặc trong /usr/share/zsh/4.3.9/functions/_sshtrong Mac OS X (thích ứng với phiên bản)
Studer

Tôi lấy tệp đó và nhập ssh <TAB> và tôi hoàn thành tên tệp. Có chuyện gì với nó vậy?
iconoclast

1

Tôi làm điều này bằng cách sử dụng danh sách tất cả các máy chủ lưu trữ trên một tên miền nhất định bằng cách sử dụng dig. Bạn có thể thay thế chức năng bên dưới bằng bất kỳ hệ thống tra cứu nào bạn muốn bao gồm tệp máy chủ hoặc danh sách tĩnh:

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

Lưu ý: Mã ở trên có thể không thay thế hoàn toàn hệ thống hoàn chỉnh cho lệnh ssh trong cấu hình của bạn. Nếu bạn gặp vấn đề với nó, hãy thử thay đổi lệnh "ssh" thành một số lệnh ngẫu nhiên khác như "mycompletetest" và xem liệu việc hoàn thành có hiệu quả không.

Cũng lưu ý rằng điều này không chuyển vùng dns mỗi khi hoàn thành! Nếu bạn sử dụng nhiều hoặc trên một miền khá tĩnh, sẽ rất hợp lý khi thực hiện tra cứu và lưu kết quả, sau đó, trong chức năng tra cứu của bạn chỉ cần đặt reply = zone_result.


Tôi không thể làm điều đó để làm việc cả. Rõ ràng tôi phải thay đổi phần trả lời, nhưng bạn có thể đưa ra một ví dụ hoạt động với văn bản tĩnh, vì vậy tôi biết nó nên ở định dạng nào? (Tôi đã thử những gì tôi hiểu trang người đàn ông để nói và sửa -k thành -K, và nó vẫn không hoạt động.)
iconoclast

Định dạng trả lời khá đơn giản, nó chỉ là một blob văn bản thẳng, một câu trả lời có thể có trên mỗi dòng. Điều dns có lẽ là phần khó khăn. Máy chủ DNS của bạn phải hỗ trợ chuyển vùng để hoạt động. Điều này thường có nghĩa là bạn phải nói chuyện với máy chủ dns chính cho tên miền được đề cập, như thế này dig axfr mydomain.com @ns1.mydomain.com. Hãy chắc chắn rằng bạn có thể chạy thủ công và một phần của đầu ra phải là một danh sách các máy chủ được đăng ký trên tên miền đó và A hoặc bất kỳ bản ghi nào. Đó là những gì tôi đã tham gia, sau đó chỉ cắt phần tên máy chủ không phải là hồ sơ đủ điều kiện.
Caleb

Pleasenote mà tôi đã viết lại mã ví dụ trong câu trả lời của mình để giải pháp cắt và dán hoàn toàn hoạt động bao gồm một tên miền mà công cụ tra cứu chuyển vùng hoạt động. Sau đó bạn có thể điều chỉnh theo bộ. Tôi xin lỗi vì bản gốc kết thúc bằng hai lỗi chính tả từ khi tôi xé ra khoảng 20 lớp nội dung bổ sung trong tệp .zshrc không liên quan đến ví dụ này.
Caleb

Lệnh đào trong backticks hiện hoạt động (cảm ơn vì đã chỉnh sửa nó!), Nhưng nó không hiển thị bất kỳ kết quả nào của lệnh đó khi tôi gõ ssh <TAB>. Có cái gì khác ngoài cái này cần phải được kích hoạt trước khi nó hoạt động không?
iconoclast

0

Tôi thích giữ known_hoststập tin băm của mình và thà không HashKnownHoststắt. Tôi thấy rằng việc gieo những gì @Gilles có với những gì đã có trong lịch sử của tôi khá hiệu quả cho nhu cầu của tôi.

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

Ngoài ra, FWIW, đây là những gì tôi đã sử dụng cho 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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.