在bash脚本中使用Expect自动进行ssh连接

问题描述

我正在尝试使用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建立在语言的基础上,该语言完全能够读取文件:

#!/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