How to configure autocompletion for ssh command with hosts from .ssh

Autocompletion is one of the most useful features of the command line, allowing you to quickly find the appropriate arguments or commands by simply pressing the Tab key. In this article, I will tell you how to set up autocompletion for a command sshso that Bash will suggest hosts specified in the file ~/.ssh/config.

Step 0. Understand why it is necessary

Sometimes the client for connecting to ssh gives a long sheet of the form super-puper-host.domain.client.cloud.hosting-provider.orgport 3515 and the user awesome-protected-user.

As a result, when connecting to a host via bash, you need to manually write something like

ssh -p 3515 awesome-protected-user@super-puper-host.domain.client.cloud.hosting-provider.org

Which looks and feels extremely awkward to my brain. That's why I've been using Alice's ssh for these purposes for a long time now:

I put it in ~/.ssh/config lines of the form

host client-host
    HostName super-puper-host.domain.client.cloud.hosting-provider.org
    User awesome-protected-user
    Port 3515

After that, I type `ssh client-host` into the console and connect to the server. All the aliases that I use regularly are entered manually automatically, and this is extremely convenient. But I decided to make this process even more convenient, so that I could enter ssh cliepress TAB and get auto-complete options.

I have never written my own autocompletes and had to google a lot to figure out how to implement this and connect it to my system. I work on Windows 10 and bash is launched via git bash using C:/Users/{username}/ as a home directory. Inside wsl I connect only when absolutely necessary and avoid it for routine admin tasks.

Step 1: Configure host autocompletion from ~/.ssh/config

By default, Bash offers file and folder completion for most commands, including sshTo set up host autocompletion, we use a Bash function called compgenwhich allows you to generate possible auto-completion options.

Below is the code that allows Bash to list hosts specified in a file ~/.ssh/configwhen typing a command ssh.

Script for autocompletion of hosts

First, create a file ~/.ssh/autocomplete.sh with content

#!/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

How does this work:

  1. Function _ssh_host_autocomplete_ssh:

    • COMP_WORDS[COMP_CWORD] — is an array containing all the arguments entered in the current line. COMP_CWORD — the index of the current word. We use this to get the word that is currently being typed.

    • awk '/^[Hh]ost / {print $2}' ~/.ssh/config – using the command awk we search for all lines in the file ~/.ssh/configwhich start with Host or hostand we display the second column, that is, the host name.

    • compgen -W "$hosts" -- "$cur_word" – team compgen is used to generate autocomplete suggestions based on the current word and a list of hosts. It outputs matching suggestions that start with the entered string.

  2. Team complete:

    • -o nospace — option specifies not to add a space after autocompletion. This is useful to continue entering options after the host.

    • -F _ssh_host_autocomplete_ssh – defines what is for the team ssh our autocomplete feature is used _ssh_host_autocomplete_ssh.

    • -o default -o bashdefault – my futile attempts to make it not offer me files from the current directory that start with this pattern. If you know how to make this work, I would be grateful.

To check the functionality of the script, we write source ~/.ssh/autocomplete.shwe start entering ssh clipress TAB and see the magic in the form of an autocomplete hint for quickly entering the target alias.

Step 2. Autostart autocomplete

Now all that's left to do is register it in .bashrc line source ~/.ssh/autocomplete.sh. Now this autocomplete will work immediately after the system starts.

Step 3: Add a convenient alias to get connection information

Sometimes you need to pass information about connecting to the project server to another admin. I used to open .ssh/config with my hands, looking for the necessary config with my eyes, copying and transferring. After improving my life with autocomplete, I immediately wanted to simplify this process. I made it so that I could write sshost client-host and immediately get the contents from the file on this host.

Created file ~/ssh/info.sh with the following contents:

#!/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"

Inside .bashrc added at the end alias sshost="bash ~/.ssh/info.sh"inside .ssh/autocomplete.sh added a line complete -o default -o bashdefault -o filenames -F _ssh_host_autocomplete sshostso that autocomplete works for this command too.

Hidden text

~/.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 (added at the end of the line)

# предыдущее содержимое
alias sshost="bash ~/.ssh/info.sh"
source ~/.ssh/autocomplete.sh

Then I restart bash or execute the command source ~/.bashrc and now I have:

  • when entering ssh, autocomplete from server alias options is immediately offered

  • if I enter the sshost command and pass the alias, I will receive a config in response, which I can immediately pass to the developer

Conclusion

With a simple Bash autocompletion setup, you can make working with SSH much easier. Now, when you type a command sshthe system will offer only those hosts that are specified in the file ~/.ssh/configwhich will save you from unnecessary file prompts and speed up your work.

This setup is ideal for those who frequently work with multiple servers and want to speed up SSH connections while avoiding hostname errors.

Thank you for your attention and I will be glad to have new subscribers to my Telegram channel @gmoreva.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *