在bash脚本中嵌入expect

时间:2016-12-15 13:45:42

标签: bash expect

我之前已经意识到类似的问题,我查看了它们并尝试应用我学到的东西并拥有以下脚本:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="testdiv" id="primary">Bananarama</div>

不幸的是,它似乎无法正常工作,我收到一条错误消息:

#!/bin/bash

if [ `hostname` = 'EXAMPLE' ]
then

/usr/bin/expect << EOD

spawn scp -rp host:~/outfiles/ /home/USERNAME/outfiles/
expect "id_rsa':"
send "PASSWORD\r"
interact

spawn scp -rp host:~/errfiles/ /home/USERNAME/errfiles/
expect "id_rsa':"
send "PASSWORD\r"
interact

expect eof

EOD

echo 'Successful download'
fi

我不知道这意味着什么以及为什么它不起作用。但是,当我使用非嵌入式期望脚本编写上述代码时:

spawn scp -rp host:~/outfiles/ /home/USERNAME/outfiles/
Enter passphrase for key '/home/USERNAME/.ssh/id_rsa': interact: spawn id exp0 not open
    while executing
"interact"

它没有任何问题。那么我做错了什么?

注意:通常当有人发布有关使用#!/usr/bin/expect spawn scp -rp host:~/outfiles/ /home/USERNAME/outfiles/ expect "id_rsa':" send "PASSWORD\r" interact spawn scp -rp host:~/errfiles/ /home/USERNAME/errfiles/ expect "id_rsa':" send "PASSWORD\r" interact 来使用expectscp的问题时,给出的答案是使用rsa密钥。我试过,不幸的是,在我的一台计算机上,gnome密钥环有一些糟糕的错误,这意味着我无法从rsa-key中删除我的密码,这正是我试图写上面的原因带有if语句的脚本。所以请不要告诉我使用rsa密钥。

1 个答案:

答案 0 :(得分:8)

您的bash脚本正在expect的标准输入上传递expect命令。这就是here-document <<EOD的作用。但是,expect ...期望其命令在man page中的文件中提供,或作为-c的参数提供。下面有三个选项。买者自负;没有人经过测试。

  1. Process substitution with here-document:

    expect <(cat <<'EOD'
    spawn ... (your script here)
    EOD
    )
    

    EOD结束here-document,然后整个事件被包装在<( )进程替换块中。结果是expect将看到一个临时文件名,其中包含here-document的内容。

    正如@Aserre所说,<<'EOD'中的引号意味着你的here-document中的所有内容都将按字面意思处理。如果这是你想要的话,请将它们关闭以扩展脚本中的bash变量等。

  2. 修改变量+ here-document:

    IFS= read -r -d '' expect_commands <<'EOD' 
    spawn ... (your script here)
    interact
    EOD
    
    expect -c "${expect_commands//
    /;}"
    

    是的,这是//之后的真实换行符 - 对我来说如何逃避它并不明显。这会将换行符转换为分号,而man page表示这是分号。

    感谢read + heredoc组合的this answer

  3. Shell变量

    expect_commands='
    spawn ... (your script here)
    interact'
    expect -c "${expect_commands//
    /;}"
    

    请注意,expect命令中的任何'(例如,在id_rsa之后)都需要替换为'\''以保留单引号块,添加文字撇号,以及然后重新进入单引号块。 //之后的换行符与上一个选项中的换行符相同。