根据我的ssh_config
档案...
配置数据解析如下:
- 命令行选项
- 用户特定文件
- 系统范围的文件
话虽如此,(是的,我知道,我可以仔细检查man ssh_config
AND man ssh
,并(希望)找到记录的默认值)。如何“打印出”所有当前设置的活动配置。例如,类似...
ssh -o Tunnel=ethernet servername -p 2210 --print-config
SSH-2.0-OpenSSH_7.0
Command Line Options
Port 2210
Host servername
Command Line Configurations
Tunnel Ethernet
Config File
...
SSH Defaults
...
AddressFamily any (???)
BatchMode no
...
这将让你清楚地知道设置了什么以及为什么。我喊道AddressFamily
特别指出了这一点,因为它是一个完美的配置选项示例,没有记录默认值。 从man ssh_config
...
指定连接时要使用的地址系列。有效参数为
any
,inet
(仅使用 IPv4)或inet6
(仅使用 IPv6)。
呃!谢谢大家建设性的建议(不只是一堆建议RTFM
)。
答案1
最近的 openssh 中有一个选项,其行为与服务器端-G
类似。-T
-G 使 ssh 在评估主机和匹配块后打印其配置并退出。
通过调用ssh -G host
您将获得用于连接特定主机的选项,这有助于调试条件匹配ssh_config
。
另外,设置更详细的日志级别(-vvv
)可以帮助调试配置解析器。
答案2
ssh -G remotehost
但这会打印出所有配置,包括默认配置(约 100 行)。有时您只想检查与默认配置的差异(当您对主机有一些特殊规则时),在这种情况下:
comm -13 <(ssh -G non-existing-host | sort) <(ssh -G remotehost | sort)
non-existing-host
此命令将和 的配置进行比较remotehost
。如果non-existing-host
确实是您的配置中没有的东西(很有可能),那么第一个ssh -G...
命令将返回默认配置。
下面是bash
相同的函数(采用一个参数 remote hostname
):
ssh-config-diff() {
local remotehost=$1
if ! [ "$remotehost" ]; then
echo "ERROR: hostname required" >&2
return 1
fi
comm -13 <(ssh-config non-existing-host | sort) <(ssh-config $remotehost | sort)
}
答案3
唯一的潜在缺点-G
是它会转储给定目标主机的整个变量集,这对于脚本编写很有用,但在视觉上进行排序可能会有点混乱。
我拼凑了一个快速而粗糙的 AWK 脚本来满足我的需求;给它一个在一行中找到的名称的片段Host
,它将打印在.ssh/config
文件中找到的配置块。请记住 (1) 一个 Host 行可以有多个条目,并且 (2) 这确实假设配置行将针对每个 Host 块缩进。此外,脚本确实不是打印出配置文件中指定的任何全局选项,因为我不需要这些。
#!/usr/bin/gawk -f
#
# Given a ~/.ssh/config file that looks like
#
# SettingOne foo
# SettingTwo bar
#
# Host hostX hostY
# SettingBlah yes
# SettingBlurg no
#
# Host hostZ
# SettingBlurg no
#
# then "print_ssh_block hostY" will print out the corresponding Setting block,
# which is considerably easier for a human to read than the output of
# "ssh -G hostY".
BEGIN {
if (ARGC != 2) {
print "Usage: print_ssh_block host_fragment"
exit 1
}
# ARGV[0] is the script file itself
# ARGV[1] is the string fragment to later match in Host lines; we don't
# want to actually process it as a filename...
hostfrag = ARGV[1]
# ...so we replace it with the filename of SSH's config, which we DO want
# to process with patterns.
ARGV[1] = ENVIRON["HOME"] "/.ssh/config"
ARGC = 2
inHostBlock = 0
}
/#/ { next }
/^[Hh][Oo][Ss][Tt] / {
# skip $1, since that's "Host"
for (i = 2; i <= NF; i++) {
# $i is the individual host; if it matches the script argument,
# set or clear the flag appropriately
inHostBlock = ($i ~ hostfrag) ? 1 : 0
if (inHostBlock) break
}
}
# When not in a matching host block, skip the indented lines.
inHostBlock == 0 && /^[[:space:]]/ { next }
# When inside a matching host block, clear the flag as soon as we reach an
# empty line.
inHostBlock == 1 && /^$/ { inHostBlock = 0 }
# When inside a matching host block, print every line we encounter.
inHostBlock == 1 { print }
对此可以进行无限的改进。真正的 AWK 大师大概可以用大约五行代码来编写它。