我正在尝试制作一个自动输入密码“root”的脚本,以将 ssh 密钥从 A 复制到 B。由于 ssh 复制在 B 上不起作用并且也无法安装,所以我使用了:
ssh root@$ip mkdir -p .ssh
cat "~/.ssh/id_rsa.pub" | ssh "root@$ip" 'cat >> .ssh/authorized_keys'
传输密钥。但 B 在重新启动时删除了其存储。所以我必须自动化这个过程。我认为期望脚本是最简单的解决方案?然而我对这些不太有经验。
#!/usr/bin/expect
#31.09.2015
set timeout 30
spawn ssh "root@$ip mkdir -p .ssh"
expect "password:"
send "root\r"
expect "(yes/no)? "
send "yes\r"
spawn cat "~/.ssh/id_rsa.pub" | ssh "root@$ip" 'cat >> .ssh/authorized_keys'
expect "password:"
send "root\r"
interact
它似乎一直有效直到第一次发送。然后却陷入困境并等待输入? (预期错误?)
这是您遇到问题的部分:
spawn ssh "root@$ip mkdir -p .ssh"
expect "password:"
send "root\r"
expect "(yes/no)? "
send "yes\r"
发送密码后,您需要等待 30 秒才能出现
(yes/no?
,但如果您之前连接过该计算机,则可能不会出现。您想要有条件地期望 y/n 提示:
spawn ssh "root@$ip mkdir -p .ssh"
expect {
"(yes/no)? " { send "yes\r"; exp_continue }
"password:" { send "root\r" }
}
expect eof
expect 命令的这种形式允许您同时查找多个字符串。如果看到的第一个是“(是/否)?”,则发送“是”并继续此期望命令。当你看到“password:”时,发送密码并让expect命令结束。
您可能想更改第二个生成命令 所以 shell 可以处理管道。
set cmd [format {cat "~/.ssh/id_rsa.pub" | ssh "root@%s" 'cat >> .ssh/authorized_keys'} $ip]
spawn sh -c $cmd
spawn
不按照您希望的方式处理输入重定向。
最简单的解决方案是创建一个单独的 shell 脚本来进行复制,并让 expect
仅处理密码提示。
这对我有用:
cat copykey.sh
:
#!/bin/bash
ssh user@host "cat >> .ssh/authorized_keys" < ~/.ssh/id_rsa.pub
cat copykey.expect
:
#!/usr/bin/expect -f
set timeout 30
spawn ssh user@host mkdir -p .ssh
expect "password:"
send "password\n"
expect "$ "
spawn ~/copykey.sh
expect "password:"
send "password\n"
expect "$ "
需要提供 ip、用户名、密码作为命令行参数(Remotelogin.exp)
#!/usr/bin/expect
set ip [lindex $argv 0]
set user [lindex $argv 1]
set password [lindex $argv 2]
spawn ssh $user@$ip
expect {
"(yes/no)?" {
send "yes\r"
expect "password:"
send "$password\r"
}
"password:" {
send "$password\r"
}
}
`
示例:./Remotelogin.exp
最简单的:
将
<your-command>
转换为:
'echo <password> | sudo -S ls | <your-command>'