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

Posted

技术标签:

【中文标题】通过 shell 脚本基于变量主机名从 ssh 配置中获取 IdentityFile【英文标题】:Grab an IdentityFile from an ssh config based on a variable hostname via shell script 【发布时间】:2018-01-22 18:39:47 【问题描述】:

我正在编写一个 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 的答案来读取配置文件并根据单个特定Hostname grep 获取单个特定IdentityFile,但我无法掌握将变量传递到啊。

到目前为止我已经尝试过

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

OUTPUT: ""

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

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

关于 awk 变量,我缺少什么?有没有更好的方法来做到这一点?

【问题讨论】:

【参考方案1】:

我很欣赏脚本尝试,但 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 抱歉,我错过了那部分。也许是时候更新了? 很遗憾,这不是我的决定,但相信我,我很乐意更新。由于这个原因,我已经对没有 sshpass 的详细选项感到厌烦。【参考方案2】:

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

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

输出:

/home/aaaa/.ssh/aaaaFILE

【讨论】:

感谢@Cyrus 的这个建议。这对我有用。我选择你的答案是因为 grep 允许更简洁。【参考方案3】:

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

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

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

但这也有效并且做同样的事情:

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

【讨论】:

感谢@valrog 的这个建议。这对我有用。

以上是关于通过 shell 脚本基于变量主机名从 ssh 配置中获取 IdentityFile的主要内容,如果未能解决你的问题,请参考以下文章

利用shell脚本执行ssh远程另一台主机执行命令并返回命令的结果集

通过ssh主机互信打通内外网,使用shell脚本自动部署测试环境

shell脚本怎么实现A主机SSH到B主机,在从B主机SSH到C主机,然后在C主机执行ps -ef命令返回C主机的进程数

Jsch使用SSH协议连接到远程Shell执行脚本

使用shell脚本实现php应用的批量更新

要在一台主机上执行shell脚本判断另一台上的某个文件是不是存在,这个shell语句该怎么写?