问题
我正尝试在 Bash 脚本中使用 Expect 来提供 SSH 密码。密码输入这部分工作正常,但我并没有像预期那样进入 SSH 会话,而是直接回到了 Bash 环境中。
我的脚本如下:
代码语言:javascript复制#!/bin/bash
read -s PWD
/usr/bin/expect <<EOD
spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com'
expect "password"
send "$PWDn"
EOD
echo "you're out"
我的脚本输出 :
代码语言:javascript复制spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com
usr@$myhost.example.com's password: you're out
我希望能在完成 SSH 会话后,再返回到我的 Bash 脚本继续执行。
我之所以先使用 Bash 脚本再调用 Expect,是因为我需要通过一个菜单来选择要连接的单元 / 设备。
回答
混合使用 Bash 和 Expect 可能不是达到期望效果的最佳方式。我会尝试只使用 Expect 来实现:
代码语言:javascript复制#!/usr/bin/expect
eval spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com
# Use the correct prompt
set prompt ":|#|\$"
interact -o -nobuffer -re $prompt return
send "my_passwordr"
interact -o -nobuffer -re $prompt return
send "my_command1r"
interact -o -nobuffer -re $prompt return
send "my_command2r"
interact
bash 的示例解决方案如下:
代码语言:javascript复制#!/bin/bash
/usr/bin/expect -c 'expect "n" { eval spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com; interact }'
另一种简化的方式【但是有安全风险】:
代码语言:javascript复制sshpass -p<password> ssh <arguments>
sshpass -ptest1324 ssh user@192.168.1.200 ls -l /tmp
上面的命令可以很容易地与 Bash 脚本集成。
但是从安全角度看,这非常危险 —— 命令行参数可能被系统上的任何其他进程读取。虽然 sshpass 有可能覆盖这些参数,但在它启动并能够执行覆盖之前,存在一个时间段,此时密码可被任何进程查看,这是极大的安全隐患。强烈建议不要将这种形式的脚本用在生产环境上。
参考
- stackoverflow question 4780893
- man expect
- man sshpass