Автодополнение — одна из самых полезных функций командной строки, позволяющая быстро подбирать подходящие аргументы или команды, просто нажав клавишу 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 Автор
буду изучать что это такое) первый раз от вас про него узнал только что