意外的expect/ssh问题

意外的expect/ssh问题

我正在寻求自动化基于 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"

(但如果有人可以回答我的第二个问题......)

相关内容