如何在Bash脚本中使用expect来为SSH命令提供密码

2024-07-01 14:58:07 浏览数 (2)

问题

我正尝试在 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

0 人点赞