问题描述
我正在尝试使用Expect执行自动化连接的shell脚本,因为不允许使用ssh键。这是我的第一个带有Expect的脚本,我觉得有些困惑。在这种情况下,我可以通过ssh进行连接,但无法关闭连接,我也不知道该怎么办?
#!/bin/bash
user=pepe
host=server
pass=`cat /tmp/password.txt`
COMMAND=df
PASSWORD=$pass expect -c "
spawn ssh $user@$host
expect "*assword*"
send \$env(PASSWORD)\r
expect {
"*be*" {send $COMMAND\r;interact}}
"
解决方法
立即的解决方法是将命令指定为ssh
的参数-然后将建立连接并且命令将运行并且连接将关闭
#!/bin/bash
user=pepe
host=server
pass=`cat /tmp/password.txt`
COMMAND=df
PASSWORD=$pass expect -c "
spawn ssh $user@$host $COMMAND
expect \"*assword*\"
send \$env(PASSWORD)\r
expect eof
"
几件事要注意:
-
expect eof
将优雅地等待生成的命令退出 - 我已转义了内部双引号。
下一步是整理报价/转义。在外壳程序脚本中嵌入另一种语言的代码时,使用带引号的heredoc是避免引用地狱的最佳方法。这意味着所有shell变量都需要通过环境传递给期望值
#!/bin/bash
export user=pepe
export host=server
export pass=`cat /tmp/password.txt`
export cmd=df
expect << 'END_EXPECT'
spawn ssh $env(user)@$env(host) $env(cmd)
expect "*assword*"
send $env(pass)\r
expect eof
END_EXPECT
我最后要做的是减少密码的暴露。 Expect建立在tcl语言的基础上,该语言完全能够读取文件:
#!/bin/bash
export user=pepe
export host=server
export pass=`cat /tmp/password.txt`
export cmd=df
expect << 'END_EXPECT'
set fh [open /tmp/password.txt]
gets $fh pass
close $fh
spawn ssh $env(user)@$env(host) $env(cmd)
expect "*assword*"
send $pass\r
expect eof
END_EXPECT
并确保对该密码文件的权限尽可能严格:
mv /tmp/password.txt ~/.local/share/pass.txt
chmod 0400 ~/.local/share/pass.txt