5

我正在编写一个 shell 脚本,我需要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 user for a specific host from ssh config file的答案来读取配置文件并 grepIdentityFile基于单个特定的单个特定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 变量时,我错过了什么?有一个更好的方法吗?

4

3 回答 3

5

我很欣赏脚本尝试,但 OpenSSH 客户端已经知道如何解析配置:

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

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

于 2017-08-15T10:57:34.263 回答
2

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

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

输出:

/home/aaaa/.ssh/aaaaFILE
于 2017-08-14T20:52:54.670 回答
1

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

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

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

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

HOSTNAME="BBBB"
awk -v host=$HOSTNAME '/Host/ && $2==host {found=1} /IdentityFile/ && found {print $2; exit}' ${SSH_CONFIG}
于 2017-08-14T22:53:36.597 回答