Получите IdentityFile из конфигурации ssh на основе имени хоста переменной с помощью сценария оболочки

Я пишу сценарий оболочки, где мне нужно получить IdentityFile из конфигурационного файла ssh. Конфигурационный файл ssh выглядит так:

​Host AAAA
    User aaaa
    IdentityFile /home/aaaa/.ssh/aaaaFILE
    IdentitiesOnly yes
    PubkeyAuthentication=yes
    PreferredAuthentications=publickey
​Host BBBB
    User bbbb
    IdentityFile /home/aaaa/.ssh/bbbbFILE
    IdentitiesOnly yes
    PubkeyAuthentication=yes
    PreferredAuthentications=publickey
​Host CCCC
    User cccc
    IdentityFile /home/aaaa/.ssh/ccccFILE
    IdentitiesOnly yes
    PubkeyAuthentication=yes
    PreferredAuthentications=publickey

Я хочу получить следующую строку IdentityFile на основании данного Hostname и положить его в переменную. Имя хоста будет предоставлено переменной оболочки с именем ${HOSTNAME},

Я смог использовать ответ в Bash extract для конкретного хоста из файла конфигурации ssh, чтобы прочитать файл конфигурации и grep для отдельного конкретного IdentityFile на основе одного конкретного Hostname, но я не могу научиться передавать переменную в awk.

Пока я пробовал

SSH_CONFIG="/home/aaaa/.ssh/config"
# Note AAAA is the hostname for this case
KEY=$(awk '/^Host AAAA$/{x=1}x&&/IdentityFile/{print $2;exit}' ${SSH_CONFIG})
echo "${KEY}" 

OUTPUT: "/home/aaaa/.ssh/aaaaFILE"

который работает, потому что я даю точное имя хоста для разбора. Но используя

SSH_CONFIG="/home/aaaa/.ssh/config"
HOSTNAME=AAAA
KEY=$(awk -vcon="${HOSTNAME}" '/^Host con$/{x=1}x&&/IdentityFile/{print $2;exit}' ${SSH_CONFIG})
echo "${KEY}" 

OUTPUT: ""

не работает. Я точно знаю ${HOSTNAME} устанавливается, потому что я настраиваю себя (и повторяю это). Я хотел бы передать переменную, потому что я не хочу, чтобы имя хоста было жестко закодировано, и не буду знать, каково это значение, пока не будет вызван скрипт.

Я также застрял с использованием и старой версии SSH (OpenSSH_6.6.1), которая не имеет удобной ssh -G HOSTNAME вариант.

Чего мне не хватает, когда дело доходит до переменных awk? Есть лучший способ сделать это?

3 ответа

Решение

С GNU grep и регулярными выражениями, совместимыми с Perl:

hostname="AAAA"
grep -Poz "Host $hostname(.*\n)*?.*IdentityFile \K.*" ~aaaa/.ssh/config

Выход:

/home/aaaa/.ssh/aaaaFILE

Я ценю попытки написания сценариев, но клиент OpenSSH уже знает, как анализировать конфигурацию:

ssh -G $hosname | grep identityfile | awk '{print $2}' | head -n 1

обратите внимание, что в нем также будут перечислены идентификаторы по умолчанию, но с IdentitiesOnly=yes он должен перечислить тот из конфигурации как первый.

Ммм, почему-то, пример, который вы разместили, содержит странные непечатаемые символы перед словом " хост" Это регулярное выражение соответствует только первой строке: /^Host/, в то время как он должен соответствовать 3 всего строк.

Я исправил это, удалив эти символы и сохранив их снова.

Итак, отвечая на ваш вопрос, вы не можете использовать переменные внутри регулярного выражения в awk.

Но это также работает и делает то же самое:

HOSTNAME="BBBB"
awk -v host=$HOSTNAME '/Host/ && $2==host {found=1} /IdentityFile/ && found {print $2; exit}' ${SSH_CONFIG}
Другие вопросы по тегам