在bash数组中将变量传递给`expect`

时间:2014-04-23 02:50:23

标签: linux bash variables for-loop expect

我正在尝试使用FOR循环迭代IP地址(在bash数组中),登录,运行脚本然后退出。该数组名为$ {INSTANCE_IPS [@]}。以下代码不起作用,因为expect似乎无法接受变量$ instance。

for instance in ${INSTANCE_IPS[@]}
  do
  echo $instance
  /usr/bin/expect -c '
  spawn ssh root@$instance;
  expect "?assword: ";
  send "<password>\r";
  expect "# ";
  send ". /usr/local/bin/bootstrap.sh\r";
  expect "# ";
  send "exit\r" '
done

然而,expect抱怨:

can't read "instance": no such variable
    while executing
"spawn ssh root@$instance"

还有一个关于stackoverflow的问题位于here,它使用环境变量来实现这一点,但是它不允许我像在数组中那样迭代不同的IP地址。

感谢任何帮助。

干杯

4 个答案:

答案 0 :(得分:4)

问题在于引用。围绕整个块的单引号不允许Bash扩展变量($instance)。

您需要切换到双引号。但是,双引号内的双引号是不允许的(除非你逃避它们),所以我们最好使用带有expect字符串的单引号。

尝试改为:

for instance in ${INSTANCE_IPS[@]}
  do
  echo $instance
  /usr/bin/expect -c "
  spawn ssh root@$instance;
  expect '?assword: ';
  send '<password>\r';
  expect '# ';
  send '. /usr/local/bin/bootstrap.sh\r';
  expect '# ';
  send 'exit\r' "
done

答案 1 :(得分:1)

for instance in ${INSTANCE_IPS[&]} ;  do
    echo $instance
    /usr/bin/expect -c '
    spawn ssh root@'$instance' "/usr/local/bin/bootstrap.sh"
    expect "password:"
    send "<password>\r"
    expect eof'
done

来自ssh手册页:

If command is specified, it is executed on the remote host instead of a login shell.

指定命令意味着期望不必等待#执行您的程序,然后等待另一个#发送命令exit。相反,当您为ssh指定命令时,它会执行该命令;它完成后退出;然后ssh自动关闭连接。

答案 2 :(得分:0)

或者,将值放在环境中,期望可以在那里找到它

for instance in ${INSTANCE_IPS[&]} ;  do
    echo $instance
    the_host=$instance /usr/bin/expect -c '
        spawn ssh root@$env(the_host) ...

答案 3 :(得分:0)

旧线程,也是其中的一个,但是我已经在expect上工作了几天。对于碰到这种情况的任何人,我相信我已经找到了一个可行的解决方案,可以解决在bash脚本中传递expect -c变量的问题:

#!/usr/bin/env bash
password="TopSecret"

read -d '' exp << EOF
set user "John Doe"
puts "\$user"
puts "$password"
EOF

expect -c "$exp"

请注意,转义引号通常是一个被引用的问题(如上面的@Roberto Reale所述),我已经使用heredoc EOF方法解决了,在传递之前bash变量评估的字符串为expect -c。与转义引号相反,所有本机expect变量都需要使用\$ 进行转义(我不是在这里首先解决 all -世界问题-我的下午日程安排被塞满了),但这应该可以大大简化问题。如果您对此概念证明有任何疑问,请告诉我。

tl; tr:正在使用用户身份验证创建[expect]守护程序脚本,并且在 之后就搞清楚了。我花了一整天的时间创建单独的bash / expect脚本,对提示进行加密密码(通过bash),每次迭代使用不同的/dev/random盐,将加密的密码保存到临时文件中,并将盐传递给期望脚本(强烈劝阻任何人通过ps轻松地找到密码,但是不能预防,因为可以替换期望脚本)。现在,我应该能够有效地将其保存在内存中。