Назад | Перейти на главную страницу

Как отредактировать завершение команды для ssh на zsh?

Я хотел бы настроить завершение команд на 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) это, вероятно, более эффективно. Если никто не ответит, я найду ответ.)

Вот соответствующая часть из моих .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

Я делаю это, используя список всех хостов в данном домене, используя 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.

Функция, обеспечивающая ssh завершение находится по адресу /usr/share/zsh/functions/Completion/Unix/_ssh в моей системе.

Также см man zshcompsys для документации (особенно выполните поиск по «host», который появляется в нескольких местах, и «ssh», который появляется в нескольких местах).

Возможно, добавление zstyle команда вашему ~/.zshrc будет делать то, что вы ищете, не изменяя функцию завершения.

Мне нравится хранить хеш 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