在EC2上运行expect脚本挂起,但在手动调用

时间:2015-07-13 17:00:29

标签: amazon-web-services ssh amazon-ec2 expect

我正在编写expect脚本来启动SSH隧道。

它在实例启动时在EC2上运行,作为从.ebextensions配置文件创建脚本的部署的一部分。

当脚本运行时,它总是卡在这一点上:

Enter passphrase for key '/home/ec2-user/id_data_app_rsa':

如果我在服务器上手动运行相同的脚本,它会成功,我可以看到隧道进程正在运行。

ps aux | grep ssh

root 19046 0.0 0.0 73660 1068 ? Ss 16:58 0:00 ssh -i /home/ec2-user/id_data_app_rsa -p222 -vfN -L 3306:X.X.X.X:3306 root@X.X.X.X

我可以通过将脚本打印到控制台来验证脚本是否正确读取SSH_PASSPHRASE

   set password $::env(SSH_PASSPHRASE)
   send_user "retrieved env variable : $password "

这是我从EC2日志中获得的调试输出:

Enter passphrase for key '/home/ec2-user/id_data_app_rsa': 
interact: received eof from spawn_id exp0

我感到困惑的是,当EC2部署者运行时,为什么它在这里不再进一步,但是在手动运行时它会继续正常运行。

这是.ebextensions中的脚本,脚本本身从#!/usr/bin/expect开始:

files:

  "/scripts/createTunnel.sh" :
   mode: "000755"
   owner: root
   group: root
   content: |
   #!/usr/bin/expect
   exp_internal 1
   set timeout 60
   # set variables
   set password $::env(SSH_PASSPHRASE)
   send_user "retrieved env variable : $password "
   spawn -ignore HUP ssh -i /home/ec2-user/id_data_app_rsa -p222 -vfN -L 3306:X.X.X.X:3306 root@X.X.X.X

   expect {
    "(yes/no)?" { send "yes\n" }
    -re "(.*)assphrase"     { sleep 1; send -- "$password\n" }
    -re "(.*)data_app_rsa"  { sleep 1; send -- "$password\n" }
    -re "(.*)assword:"      { sleep 1; send -- "$password\n" }

    timeout     { send_user "un-able to login: timeout\n"; return }
    "denied"    { send_user "\nFatal Error: denied \n"}
    eof         { send_user "Closed\n" ; return }
}
interact

2 个答案:

答案 0 :(得分:0)

你的问题在这里:

set password $::env(SSH_PASSPHRASE)

以及shell使用环境变量的方式。调用脚本时,您假设已设置环境变量。根据脚本的调用方式,可能不会设置$ :: env(SSH_PASSPHRASE),从而导致变量为null / blank。运行init脚本(或cloud-init)时,它们不会与登录shell的环境一起运行。因此,您不应该假设设置了.profile或/ etc / profile环境变量,而是明确地提供或设置它们。

可能的解决方案可能是

. ~ec2-user/.profile /path/to/above.script

答案 1 :(得分:0)

我们终于解决了这个问题。有两件事似乎有问题:

  • 将最终interact更改为expect eof
  • 减少了 expect模式匹配尽可能多。

我们在测试中注意到,期望似乎错误地匹配,例如,发送密码时应该发送“是”和“#”。匹配'是/否'提示。

这是我们最终编写的最终脚本,以防对其他任何人有用:

     #!/usr/bin/expect
     exp_internal 1
     set timeout 60
     # set variables
     set password $::env(SSH_TUNNEL_PASSPHRASE)
     spawn -ignore HUP ssh -i /home/ec2-user/id_data_rsa -p222 -vfN   -L 3306:X.X.X.X:3306 root@X.X.X.X
     expect {
         "(yes/no)?" { send "yes\r" }
         "Enter passphrase" { sleep 2; send -- "$password\r"; sleep 2; exit }
     }
     expect eof