zsh:ssh 的补全规则

zsh:ssh 的补全规则

在 中zsh,我可以自动完成来自 的主机名/etc/hosts,即:

ssh f<TAB>

将为以 开头的主机提供补全f

这是在以下位置配置的/usr/share/zsh/functions/Completion/Unix/_hosts

local ipstrip='[:blank:]#[^[:blank:]]#'

zstyle -t ":completion:${curcontext}:hosts" use-ip && useip=yes
[[ -n $useip ]] && ipstrip=
if (( ${+commands[getent]} )); then
  _cache_hosts=(${(s: :)${(ps:\t:)${(f)~~"$(_call_program hosts getent hosts 2>/dev/null)"}##${~ipstrip}}})
else
  _cache_hosts=(${(s: :)${(ps:\t:)${${(f)~~"$(</etc/hosts)"}%%\#*}##${~ipstrip}}})
fi

....

_hosts=( "$_cache_hosts[@]" )

但是,它仅在/etc/hosts文件格式为“IP”“主机名”时才有效,即:

192.168.1.4      foo.mydomain.com

如果 IP 丢失,它将无法工作:

                 foo.mydomain.com

如何修改完成脚本,以便没有 IP 的主机名也完成?

没有 IP 的主机名补全/etc/hostsbash_completion.所以我只是想在zsh.

答案1

我建议这样做,这将使用您的(和系统的)ssh 已知主机文件:

zstyle -e ':completion:*:(ssh|scp|sftp|rsh|rsync):hosts' hosts 'reply=(${=${${(f)"$(cat {/etc/ssh_,~/.ssh/known_}hosts(|2)(N) /dev/null)"}%%[# ]*}//,/ })'

如果您仍然想使用 /etc/hosts 代替:

strip='[:blank:]#[^[:blank:]]#'
zstyle -e ':completion:*:(ssh|scp|sftp|rsh|rsync):hosts' hosts 'reply=(${(s: :)${(ps:\t:)${${(f)~~"$(</etc/hosts)"}%%\#*}##${~strip}}})'

祝你好运!

答案2

添加过滤功能/usr/share/zsh/functions/Completion/Unix/_hosts

provide_missing_ip() {
   while read x ; do 
      set -- $x
      if [ ! "$1" ] || [ "${1%%[^#]*}" ] || [ "$2" ] ; then
          echo "$x"
      else
          ip=`dig +short $2`
          [ "$ip" ] || ip="240.0.0.0"
          printf "%s\t%s\n" $1 $2
      fi
   done
}

怎么运行的:

  1. 如果有两个条目、一个空白或一个注释,则只需输出它们即可。
  2. 如果只有主机名,请尝试提供知识产权地址与dig.
  3. 如果做不到这一点,(不应该发生,但假设这是出于测试目的而故意伪造的主机名),请使用无害的虚拟主机名知识产权地址“240.0.0.0“, (看班德拉米的回答 ”相当于 /dev/null 的 IP 地址)。

使用新函数来解析麻烦的完成代码中的getentor的输出:< /etc/hosts

if (( ${+commands[getent]} )); then
  _cache_hosts=(${(s: :)${(ps:\t:)${(f)~~"$(_call_program hosts getent hosts 2>/dev/null | provide_missing_ip )"}##${~ipstrip}}})
else
  _cache_hosts=(${(s: :)${(ps:\t:)${${(f)~~"$(provide_missing_ip </etc/hosts)"}%%\#*}##${~ipstrip}}})
fi

答案3

hosts文件必须采用 格式IP_address canonical_hostname [aliases...],因此您的方法应该是修复您的主机文件,而不是让一个程序片段解决损坏的文件。如果您的程序损坏了,其他程序也可能会出现问题hosts,因此这将是您的用例的唯一合理的解决方案。如果您的目标是动态 IP,并且您不想使用上面提供的任何更好的解决方法,请考虑编写一个脚本,hosts根据此更改的地址动态更改您的 IP。

相关内容