我正在寻求自动化基于 ssh 密码的登录(以及登录后的一系列操作)。
我知道 ssh 密码提示会绕过 STDIN。为此,我编写了一个快速预期脚本。
spawn ssh -o StrictHostKeyChecking=No $USERNAME@$HOST
expect {
timeout { send_user "\nFailed to get password prompt\n"; exit 1 }
eof { send_user "\nSSH failure for $HOST\n"; exit 1 }
"*assword"
}
send "Pasword123\r"
expect {
timeout { send_user "\nLogin failed. Password incorrect.\n"; exit 1}
"*\$ "
}
sleep 1
send "echo 002-READY\r"
interact
这似乎按我的预期工作。但是,当我在“交互”之后将进一步的命令输入正在运行的脚本的 STDIN 时,它们似乎没有到达 ssh 会话,例如
$ cat feed.sh
#!/bin/bash
sleep 3; echo "cat /etc/hosts"
$ ./feed.sh | ./ssh_expect_script
但是它确实检测到 EOF 并终止会话。
(请不要告诉我解决方案是使用密钥对;交互式密码成为特定约束是有原因的。)
如何通过 Expect 将输入路由到远程会话?
或者,如何将密码发送到 ssh?
(关于替代问题,我使用 PHP 作为控制机制。作为最后的手段,我可以动态生成整个期望脚本。我尝试直接写入 tty,但这只是返回到我的屏幕上。我还查看了在 ssh-askpass,但文档仅提到密码短语/我找不到不依赖于桌面环境运行的版本)。
答案1
Tcl 和 Expect 不会使用 stdin 自动执行任何操作。你需要积极地阅读它:
send "echo 002-READY\r"
expect -re {\$ $}
fconfigure stdin -blocking no
while {[gets stdin line] != 0} {
# prevent an infinite loop waiting for data on stdin
if {$line eq ""} break
send "$line\r"
expect -re {\$ $}
}
# finished sending the input: now log off gracefully
send "exit\r"
expect eof
关于sleep
——通常情况下,发送完某些内容后您不需要睡觉如果你的expect
模式正确。我建议您expect -d program.exp
在开发脚本时使用它来验证您的模式是否匹配。
答案2
啊 - 需要 CR 而不是 NL
echo -e "cat /etc/hosts\r"
(但如果有人可以回答我的第二个问题......)