通过shell脚本在ssh配置文件中根据变量主机名获取一个IdentityFile。

5

我正在编写一个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变量提供。

我已经成功使用Bash extract user for a particular host from ssh config file中的答案读取配置文件并基于单个特定的HostnameIdentityFile进行grep,但我无法掌握将变量传递给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"

因为我提供了准确的主机名进行解析,所以这个方法可以正常工作。但是请注意,使用HTML标签时需要遵循格式要求。

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个回答

5
我很欣赏您的脚本尝试,但是OpenSSH客户端已经知道如何解析配置文件:
ssh -G $hosname | grep identityfile | awk '{print $2}' | head -n 1

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

正如我上面提到的,我也被困在使用较旧版本的ssh(OpenSSH_6.6.1)上,它没有方便的ssh -G HOSTNAME选项。除非你想为我制作一个Debian软件包,否则我将无法使用ssh -G进行脚本编写。 - Wimateeka
1
@Wimateeka 抱歉,我错过了那部分。也许是更新的时候了? - Jakuje
很不幸,这不是我的决定,但相信我,我很乐意更新。由于这个问题,我已经因为没有sshpass的冗长选项而受到了批评。 - Wimateeka

2

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

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

Output:

/home/aaaa/.ssh/aaaaFILE

谢谢你的建议,@Cyrus。这对我很有用。我选择了你的答案,因为grep更加简洁。 - Wimateeka

1

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

我通过删除这些字符并重新保存来修复了这个问题。

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

但这也可以工作并完成相同的任务:

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

谢谢您的建议,@valrog。这对我很有帮助。 - Wimateeka

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接