如何使用'expect'将公钥复制到主机?

Ale*_*lex 7 ssh tcl expect

我使用以下语法将公钥复制到主机,以便能够在没有密码查询的情况下登录到主机:

ssh-copy-id $hostname 
Run Code Online (Sandbox Code Playgroud)

其中$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)?
Run Code Online (Sandbox Code Playgroud)

我试图解决我的问题expect,这是我到目前为止(包括所有的意见和建议):

#!/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"
  }

}
Run Code Online (Sandbox Code Playgroud)

这可以正确地"捕获"第一次交互,但不是第二次交互.似乎正在使用正确的密码(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 }
Run Code Online (Sandbox Code Playgroud)

虽然我既不是tcl也不是期望专家,但似乎期望向ssh-copy-id命令发送正确的字符串(即密码).但仍然存在问题,因为上述expect命令不会将公钥复制到主机.

Amo*_*mos 1

我想分享我的 tcl/expect 脚本。它运作得很好。

\n\n
#!/usr/bin/env tclsh\n\npackage require Expect\n\nset prompt {[$\xe2\x9d\xaf#] }\nset keyfile "~/.ssh/id_rsa.pub"\nset needcopy 0\n\nif {![file exists $keyfile]} {\n    spawn ssh-keygen\n    interact\n}\n\nspawn ssh $argv\n\nexpect {\n    {continue connecting (yes/no)?} {\n        send "yes\\r"\n        exp_continue\n    }\n    {[Pp]ass*: } {\n        set needcopy 1\n        interact "\\r" {\n            send "\\r"\n            exp_continue\n        }\n    }\n    $prompt\n}\n\nif {$needcopy} {\n    set fd [open $keyfile]\n    gets $fd pubkey\n    close $fd\n    send " mkdir -p ~/.ssh\\r"\n    expect $prompt\n    send " cat >> ~/.ssh/authorized_keys <<EOF\\r$pubkey\\rEOF\\r"\n    expect $prompt\n}\ninteract\n
Run Code Online (Sandbox Code Playgroud)\n