zsh에서 ssh의 명령 완성을 편집하는 방법은 무엇입니까?


11

입력 한 후 호스트 이름을 표시하도록 zsh에서 명령 완료를 설정하고 싶습니다.

ssh [TAB]

내 .ssh / config 파일에서 이름을 가져오고 (그리고 바람직하게는 known_hosts 및 / etc / hosts 및 그 밖의 다른 곳에서) 하나의 단일 목록을 제시하십시오.

현재이 중 일부를 수행하지만

  1. .ssh / config를 전혀 사용하지 않습니다.
  2. .ssh / config를 사용하면 사용자 이름을 입력 할 필요가 없지만 먼저 사용자 이름이 필요합니다.
  3. 여러 목록을 제공합니다 (아마도 known_hosts에서 하나와 / etc / hosts에서 다른 하나).

따라서 ssh [TAB]를 입력 한 후 알려진 사용자 이름과 알려진 호스트 이름을 (바람직하게는 단일) 목록에 포함하고 싶습니다

(1 때문에 답변이 여기에 저장되며 2) 아마도 더 효율적일 것입니다. 아무도 대답하지 않으면 답을 찾아 낼 것입니다.)


이 수퍼 유저에 대한 질문이 될 것이라고 생각
에티엔 느 페로

사실, 지금 살펴보면 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

영역 전송 조회가 작동하는 도메인 이름을 포함하여 완전히 작동하는 잘라 내기 및 붙여 넣기 솔루션으로 예제 코드를 다시 작성했습니다. 그런 다음 스위트에 맞게 조정할 수 있습니다. 나는이 예제와 관련이없는 .zshrc 파일에있는 약 20 개의 추가 레이어를 찢어 냈을 때 두 번의 오타로 끝나는 원본에 대해 사과합니다.
Caleb

백틱의 dig 명령은 이제 작동하지만 (편집 해 주셔서 감사합니다!), 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.