通过shell脚本

时间:2017-08-14 20:42:54

标签: shell parsing awk ssh ssh-config

我正在编写一个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

我希望根据给定的IdentityFile获取Hostname之后的字符串,并将其放入变量中。主机名将由名为${HOSTNAME}的shell变量提供。

我能够使用Bash extract user for a particular host from ssh config file上的答案来阅读配置文件,并根据单个特定IdentityFile来查看单个特定Hostname的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"

这是有效的,因为我给出了要解析的确切主机名。 但是使用

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 个答案:

答案 0 :(得分:2)

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

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

输出:

/home/aaaa/.ssh/aaaaFILE

答案 1 :(得分:2)

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

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

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

答案 2 :(得分:1)

mmm由于某种原因,您发布的示例在主机字之前具有奇怪的不可打印字符。此正则表达式仅匹配第一行:/^Host/,而它应匹配总共3行。

我通过删除这些字符并再次保存来修复它。

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

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

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