通过 shell 脚本基于可变主机名从 ssh 配置中获取 IdentityFile

Grab an IdentityFile from an ssh config based on a variable hostname via shell script

我正在编写 shell 脚本,我需要从 ssh 配置文件中获取 IdentityFile。 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

我想根据给定的 Hostname 获取 IdentityFile 后面的字符串并将其放入变量中。主机名将由名为 ${HOSTNAME}.

的 shell 变量提供

我能够使用 处的答案读取配置文件并根据单个特定 Hostname grep 查找单个特定 IdentityFile,但我不能掌握将变量传递给 awk 的窍门。

到目前为止我已经试过了

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

OUTPUT: ""

不起作用。我知道一个事实 ${HOSTNAME} 正在设置,因为我正在设置自己(并回应它)。我想传递一个变量,因为我不想对主机名进行硬编码,并且在调用脚本之前不知道该值是什么。

我也一直在使用旧版本的 ssh (OpenSSH_6.6.1),它没有方便的 ssh -G HOSTNAME 选项。

关于 awk 变量,我错过了什么?有更好的方法吗?

使用 GNU grep 和 Perl 兼容的正则表达式:

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

输出:

/home/aaaa/.ssh/aaaaFILE

嗯,出于某种原因,您发布的示例在 Host 字之前有奇怪的不可打印字符。这个正则表达式只匹配第一行:/^Host/,而它应该匹配总共 3 行。

我通过删除这些字符并再次保存来解决这个问题。

所以,回答你的问题,你不能在 awk 的正则表达式中使用变量。

但这也行得通:

HOSTNAME="BBBB"
awk -v host=$HOSTNAME '/Host/ && ==host {found=1} /IdentityFile/ && found {print ; exit}' ${SSH_CONFIG}

感谢脚本尝试,但 OpenSSH 客户端已经知道如何解析配置:

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

请注意,它还会列出默认身份,但是 IdentitiesOnly=yes 它应该将配置中的身份列为第一个。