zsh: regras de conclusão para o ssh

6

em zsh , posso preencher automaticamente nomes de host de /etc/hosts , ou seja:

ssh f<TAB>

oferecerá conclusões para hosts começando com f .

Isso está configurado em /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[@]" )

no entanto, ele só funciona se /etc/hosts file tiver o formato 'IP' 'hostname', por exemplo:

192.168.1.4      foo.mydomain.com

não funcionará se o IP estiver ausente:

                 foo.mydomain.com

Como posso modificar o script de conclusão, para que nomes de host sem IP também sejam concluídos?

A conclusão de nomes de host sem IP de /etc/hosts funciona bem em bash_completion . Então, estou apenas tentando obter o mesmo comportamento em zsh .

    
por 400 the Cat 06.07.2017 / 19:57

3 respostas

3

Eu recomendaria fazer isso, o que usaria o arquivo de hosts conhecidos do ssh (e do sistema) em seu lugar:

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

Se você ainda deseja usar / etc / hosts:

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

Boa sorte!

    
por 11.07.2017 / 18:50
0

Adicione uma função de filtro a /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
}

Como funciona:

  1. Se houver duas entradas, um espaço em branco ou um comentário, apenas imprima isso.
  2. Se houver apenas um nome de host, tente fornecer um endereço IP com dig .
  3. Se isso falhar (o que não deve acontecer, mas vamos dizer que é um nome de host falso intencionalmente para propósitos de teste), use um endereço IP inofensivo de > 240.0.0.0 ", (veja resposta de Bandrami a " endereço IP equivalente a / dev / null " ).

Use a nova função para analisar a saída de getent ou < /etc/hosts no código de conclusão problemático:

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
    
por 09.07.2017 / 17:51
-1

O arquivo hosts deve estar no formato IP_address canonical_hostname [aliases...] , portanto, sua abordagem deve ser para corrigir o arquivo de hosts, não para obter um fragmento de programa trabalhando em torno de seu arquivo quebrado. Outros programas também podem ter problemas, se o seu hosts estiver quebrado, então essa seria a única solução sensata para o seu caso de uso. Se for um IP dinâmico que você está segmentando e não quiser usar nenhuma das melhores alternativas fornecidas acima, considere escrever um script que altere dinamicamente seu hosts de acordo com esse endereço em mudança.

    
por 15.07.2017 / 09:43