【发布时间】:2017-12-22 18:37:46
【问题描述】:
我正在使用以下语法将公钥复制到主机,以便之后能够登录到主机而无需密码查询:
ssh-copy-id $hostname
其中$hostname 是带有用户名的系统的主机名,例如root@123.456.789.100。但是,此命令需要至少一个密码查询和 - 有时 - 类型的额外交互:
The authenticity of host 'xxx (xxx)' can't be established.
RSA key fingerprint is xxx.
Are you sure you want to continue connecting (yes/no)?
我试图用expect 解决我的问题,这是我目前所拥有的(包含所有 cmets 和建议):
#!/usr/bin/expect
set timeout 9
set hostname [lindex $argv 0]
spawn ssh-copy-id $hostname
expect {
timeout { send_user "\nFailed to get password prompt\n"; exit 1 }
eof { send_user "\nSSH failure for $hostname\n"; exit 1 }
"*re you sure you want to continue connecting" {
send "yes\r"
exp_continue
}
"*assword*" {
send "fg4,57e4h\r"
}
}
只要它正确地“捕捉”第一个交互,但不能正确“捕捉”第二个交互,这就是有效的。似乎正在使用正确的密码(fg4,57e4h),但是当我尝试登录主机时,仍然要求我输入密码。我还检查了.ssh/authorized_hosts 中没有任何条目。使用的密码也绝对正确,因为我可以将其复制并粘贴到登录。该脚本不会产生任何错误,但会产生以下exp_internal 1 输出:
./expect_keygen XXX
spawn ssh-copy-id XXX
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {3602}
expect: does "" (spawn_id exp6) match glob pattern "*re you sure you want to continue connecting"? no
"*assword*"? no
XXX's password:
expect: does "XXX's password: " (spawn_id exp6) match glob pattern "*re you sure you want to continue connecting"? no
"*assword*"? yes
expect: set expect_out(0,string) "XXX's password: "
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) "XXX's password: "
send: sending "fg4,57e4h\r" to { exp6 }
虽然我既不是 tcl 也不期望专家,但似乎期望将正确的字符串(即密码)发送到 ssh-copy-id 命令。但是,由于上述期望命令没有将公钥复制到主机,因此肯定存在问题。
【问题讨论】:
-
你为什么不用
ssh-copy-id?这就是它的用途。 -
这简化了任务;但它会与我的代码 sn-p 一起工作吗?那么可选的是/否问题呢,这是否也会被处理(我现在无法检查)。
-
尝试期待脚本末尾的提示。在您的脚本中,生成的过程将在发送密码后立即结束,并且不保证整个 ssh-id-copy 过程完成。