Автодополнение — одна из самых полезных функций командной строки, позволяющая быстро подбирать подходящие аргументы или команды, просто нажав клавишу Tab. В этой статье я расскажу, как настроить автодополнение для команды ssh, чтобы Bash подсказывал хосты, указанные в файле ~/.ssh/config.
Шаг 0. Понять зачем это нужно
Иногда клиент для подключения к ssh выдает длинную простыню вида super-puper-host.domain.client.cloud.hosting-provider.org, порта 3515 и пользователя awesome-protected-user.

В итоге при подключении на хост через bash надо руками писать что-то вроде
ssh -p 3515 awesome-protected-user@super-puper-host.domain.client.cloud.hosting-provider.org
Что выглядит и воспринимается моим мозгом крайне неудобно. Поэтому я уже давно использую ssh алиасы для этих целей:
Кладу в ~/.ssh/config строки вида
host client-host
HostName super-puper-host.domain.client.cloud.hosting-provider.org
User awesome-protected-user
Port 3515
После чего я в консоли вбиваю `ssh client-host` и подключаюсь на сервер. Все алиасы, которыми пользуюсь регулярно, вбиваются руками на автомате и это крайне удобно. Но я решил этот процесс сделать еще удобнее, чтобы можно было вбить ssh clie, нажать TAB и получить варианты для автоматического завершения.
Свои автокомплиты не писал никогда и пришлось много погуглить, чтобы разобраться как это реализовать и подключить у себя на системе. Работаю на Windows 10 и bash запускается через git bash с использованием C:/Users/{username}/ в качестве домашней директории. Внутри wsl подключаюсь только при острой необходимости и избегаю для рядовых админских задач.
Шаг 1. Настройка автодополнения хостов из ~/.ssh/config
По умолчанию Bash предлагает автодополнение файлов и папок для большинства команд, включая ssh. Чтобы настроить автодополнение хостов, мы используем функцию Bash под названием compgen, которая позволяет генерировать возможные варианты автодополнения.
Ниже приведен код, который позволяет Bash выводить список хостов, заданных в файле ~/.ssh/config, при наборе команды ssh.
Скрипт для автодополнения хостов
Сначала создаем файл ~/.ssh/autocomplete.sh с содержимым
#!/bin/bash
# Функция для автодополнения хостов из файла .ssh/config
_ssh_host_autocomplete() {
local cword hosts
cword=${COMP_WORDS[COMP_CWORD]}
hosts=$(grep -i '^host ' ~/.ssh/config | cut -c 6- | grep -Fv '*')
COMPREPLY=($(compgen -W "$hosts" -- "$cword"))
}
# Включаем автодополнение для скрипта
complete -o default -o bashdefault -o filenames -F _ssh_host_autocomplete ssh
Как это работает:
-
Функция
_ssh_host_autocomplete_ssh:COMP_WORDS[COMP_CWORD]— это массив, содержащий все введенные в текущей строке аргументы.COMP_CWORD— индекс текущего слова. Мы используем это, чтобы получить слово, которое вводится в данный момент.hosts=$(grep -i '^host ' ~/.ssh/config | cut -c 6- | grep -Fv '*')— грепает все хосты из файлаcompgen -W "$hosts" -- "$cur_word"— командаcompgenиспользуется для создания предложений автодополнения на основе текущего слова и списка хостов. Она выводит подходящие варианты, которые начинаются с введенной строки.
-
Команда
complete:-F _ssh_host_autocomplete_ssh— определяет, что для командыsshиспользуется наша функция автодополнения_ssh_host_autocomplete_ssh.
Чтобы проверить работоспособность скрипта пишем source ~/.ssh/autocomplete.sh, начинаем вводить ssh cli, жмем TAB и видим магию в виде подсказки автокомплита для быстрого ввода целевого алиаса.
Шаг 2. Автозапуск автокомплита
Теперь дело за малым — прописать в .bashrc строчку source ~/.ssh/autocomplete.sh. Теперь этот автокомплит будет работать сразу после запуска системы.
Шаг 3. Добавление удобного алиаса для получения информации о подключении
Иногда нужно передать другому админу информацию о подключении к серверу проекта. Раньше я открывал .ssh/config руками, искал глазами нужный конфиг, копировал и передавал. После улучшения жизни с автокомплитом сразу захотелось упростить и этот процесс. Сделал так, чтобы можно было написать sshost client-host и сразу получить содержимое из файла именно по этому хосту.
Создал файл ~/ssh/info.sh со следующим содержимым:
#!/bin/bash
# Скрипт для получения параметров подключения для хостов по регулярному выражению
PATTERN=$1
if [ -z "$PATTERN" ]; then
echo "Usage: $0 <host-pattern>"
exit 1
fi
SSH_CONFIG="$HOME/.ssh/config"
# Проверяем, существует ли файл .ssh/config
if [ ! -f "$SSH_CONFIG" ]; then
echo "Error: SSH config file not found."
exit 1
fi
# Извлекаем все строки для хостов, которые соответствуют переданному регулярному выражению
awk -v pattern="$PATTERN" '
tolower($1) == "host" && $2 ~ pattern {found=1; print; next}
found && tolower($1) == "host" {found=0}
found {print}
' "$SSH_CONFIG"
Внутри .bashrc добавил в конце alias sshost="bash ~/.ssh/info.sh", внутри .ssh/autocomplete.sh добавил строчку complete -o default -o bashdefault -o filenames -F _ssh_host_autocomplete sshost, чтобы для этой команды тоже работал автокомплит.
Скрытый текст
~/.ssh/autocomplete.sh
#!/bin/bash
# Функция для автодополнения хостов из файла .ssh/config
_ssh_host_autocomplete() {
local cword hosts
cword=${COMP_WORDS[COMP_CWORD]}
hosts=$(grep -i '^host ' ~/.ssh/config | cut -c 6- | grep -Fv '*')
COMPREPLY=($(compgen -W "$hosts" -- "$cword"))
}
# Включаем автодополнение для скрипта
complete -o default -o bashdefault -o filenames -F _ssh_host_autocomplete sshost
complete -o default -o bashdefault -o filenames -F _ssh_host_autocomplete ssh
~/.ssh/info.sh
#!/bin/bash
# Скрипт для получения параметров подключения для хостов по регулярному выражению
PATTERN=$1
if [ -z "$PATTERN" ]; then
echo "Usage: $0 <host-pattern>"
exit 1
fi
# Путь к файлу .ssh/config (может быть скорректирован, если он в другом месте)
SSH_CONFIG="$HOME/.ssh/config"
# Проверяем, существует ли файл .ssh/config
if [ ! -f "$SSH_CONFIG" ]; then
echo "Error: SSH config file not found."
exit 1
fi
# Извлекаем все строки для хостов, которые соответствуют переданному регулярному выражению
awk -v pattern="$PATTERN" '
tolower($1) == "host" && $2 ~ pattern {found=1; print; next}
found && tolower($1) == "host" {found=0}
found {print}
' "$SSH_CONFIG"
~/.bashrc (добавленные в конце файла строки)
# предыдущее содержимое
alias sshost="bash ~/.ssh/info.sh"
source ~/.ssh/autocomplete.sh
Дальше перезапускаю bash или выполняю команду source ~/.bashrc и теперь у меня:
при вводе ssh сразу предлагается автокомплит из вариантов алиасов серверов
если введу команду sshost, передам алиас то получу в ответ конфиг, который сразу можно передать разработчику
Заключение
С помощью простой настройки автодополнения в Bash вы можете значительно упростить работу с SSH. Теперь, когда вы будете набирать команду ssh, система предложит только те хосты, которые указаны в файле ~/.ssh/config, что избавит вас от лишних файловых подсказок и ускорит работу.
Эта настройка идеально подходит для тех, кто часто работает с множеством серверов и хочет ускорить подключение через SSH, избегая ошибок в именах хостов.
Благодарю за внимание и буду рад новыми подписчиками на свой Telegram канал @gmoreva.
Комментарии (15)

mavir
09.09.2024 10:26+3А какой линукс используете? Так как в Ubuntu из коробки есть автоподстановка для ssh. И не только названия хостов, но и, например, опций. Так же чтение подключаемых конфигов инструкцией include

amorev Автор
09.09.2024 10:26Я на windows сижу с 2018. До этого на ubuntu работал, но достали ошибки диска (`fsck -f /dev/sda1` достало вводить после каждой гибернации)
На wsl у меня 22.04 ubuntu, но ей пользуюсь редко.
Круто, что из коробки уже это есть, но я не нашел инфы по этой теме

Johan_Palych
09.09.2024 10:26+3Должен быть установлен:
sudo apt install bash-completion
https://github.com/scop/bash-completion/tree/main/completions
Autocomplete server names for SSH and SCP
https://unix.stackexchange.com/questions/136351/autocomplete-server-names-for-ssh-and-scp
Autocomplete server names for SSH and SCP for Git Bash
https://gist.github.com/nhthai2005/f956a0e6cfc3b38f72f0df1a239a4e68ls /usr/share/bash-completion/completions/ | grep ssh

amorev Автор
09.09.2024 10:26+1это все для wsl может быть справедливо. А я нативно на windows запускаю git bash

Habetdin
09.09.2024 10:26+1мои тщетные попытки заставить его не предлагать мне файлы из текущей директории, которые начинаются по этому паттерну. Если знаете как это сделать, чтобы работало, то буду признателен.
@amorev Попробуйте убрать все лишние опции и начать с нуля, добавляя только нужные :)
Немного переделал для себя
autocomplete.sh, чтобы предлагались в т.ч. и множественные алиасы (Host foo bar baz), но игнорировались wildcard-конфигурации (Host *,Host *.host.dev):#!/bin/bash _autocomplete_ssh_host() { local cword hosts cword=${COMP_WORDS[COMP_CWORD]} hosts=$(grep -i '^host ' ~/.ssh/config | cut -c 6- | grep -Fv '*') COMPREPLY=($(compgen -W "$hosts" -- "$cword")) } complete -F _autocomplete_ssh_host ssh
amorev Автор
09.09.2024 10:26Это очень круто! Спасибо большое) Статью обновлю! Ваш способ заметно круче моего!

mkpv
Не смотрели в сторону fzf? Он умеет в автокомплит SSH из коробки.
amorev Автор
буду изучать что это такое) первый раз от вас про него узнал только что