Автодополнение — одна из самых полезных функций командной строки, позволяющая быстро подбирать подходящие аргументы или команды, просто нажав клавишу 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 cur_word
    # Получаем текущее слово, которое набирается
    cur_word="${COMP_WORDS[COMP_CWORD]}"

    # Получаем список всех хостов из .ssh/config
    local hosts=$(awk '/^[Hh]ost / {print $2}' ~/.ssh/config)

    # Используем стандартную функцию для автодополнения на основе списка хостов
    COMPREPLY=($(compgen -W "$hosts" -- "$cur_word"))
}

# Включаем автодополнение для скрипта
complete -o default -o bashdefault -o filenames -F _ssh_host_autocomplete ssh

Как это работает:

  1. Функция _ssh_host_autocomplete_ssh:

    • COMP_WORDS[COMP_CWORD] — это массив, содержащий все введенные в текущей строке аргументы. COMP_CWORD — индекс текущего слова. Мы используем это, чтобы получить слово, которое вводится в данный момент.

    • awk '/^[Hh]ost / {print $2}' ~/.ssh/config — с помощью команды awk мы ищем все строки в файле ~/.ssh/config, которые начинаются с Host или host, и выводим второй столбец, то есть имя хоста.

    • compgen -W "$hosts" -- "$cur_word" — команда compgen используется для создания предложений автодополнения на основе текущего слова и списка хостов. Она выводит подходящие варианты, которые начинаются с введенной строки.

  2. Команда complete:

    • -o nospace — опция указывает не добавлять пробел после автодополнения. Это полезно, чтобы продолжать ввод опций после хоста.

    • -F _ssh_host_autocomplete_ssh — определяет, что для команды ssh используется наша функция автодополнения _ssh_host_autocomplete_ssh.

    • -o default -o bashdefault — мои тщетные попытки заставить его не предлагать мне файлы из текущей директории, которые начинаются по этому паттерну. Если знаете как это сделать, чтобы работало, то буду признателен.

Чтобы проверить работоспособность скрипта пишем 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 cur_word
    # Получаем текущее слово, которое набирается
    cur_word="${COMP_WORDS[COMP_CWORD]}"

    # Получаем список всех хостов из .ssh/config
    local hosts=$(awk '/^[Hh]ost / {print $2}' ~/.ssh/config)

    # Используем стандартную функцию для автодополнения на основе списка хостов
    COMPREPLY=($(compgen -W "$hosts" -- "$cur_word"))
}

# Включаем автодополнение для скрипта
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.

Комментарии (3)


  1. mkpv
    09.09.2024 10:26

    Не смотрели в сторону fzf? Он умеет в автокомплит SSH из коробки.


    1. amorev Автор
      09.09.2024 10:26

      буду изучать что это такое) первый раз от вас про него узнал только что


  1. mavir
    09.09.2024 10:26

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