2016-12-15 82 views
2

我意识到类似的问题已经被问过,我看着他们,尝试运用我所学到的并具有以下脚本:嵌入bash脚本内的期望

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

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

注意:通常当有人发布关于使用expect来使用scpssh的问题时,给出的答案是使用rsa密钥。我试过了,不幸的是,在我的一台电脑上有一些侏儒密钥环,这意味着我无法从rsa-key中删除我的密码,这正是我试图用if编写上述脚本的原因声明。所以请不要告诉我使用rsa密钥。

+1

如果您希望完全**执行**定界符之间的文本(在解释之前没有变量或特殊字符扩展),则必须引用您的here-doc定界符,如下所示: '/ usr/bin/expect <<“EOD”... EOD“。 [这个问题](http://stackoverflow.com/questions/4937792/using-variables-inside-a-bash-heredoc)是相似的,它有相同的问题,但反过来。 – Aserre

+0

我只是试过'/ usr/bin/expect <<“EOD”'但它仍然给出错误'spawn scp -rp host:〜/ outfiles // home/USERNAME/outfiles/ 输入密钥'/ home /USERNAME/.ssh/id_rsa':interact:spawn id exp0未打开 执行中 “interact” 成功下载 ' –

回答

3

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

  1. Process substitution与这里文档:

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

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

    正如@Aserre指出的那样,<<'EOD'中的引号表示您的here-document中的所有内容都将按照字面意思处理。如果这是你想要的,把它们放在脚本内部展开bash变量等。

  2. 编辑变+ here文档:

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

    是的,这是//后一个真正的换行符 - 这不是明显,我怎么逃生呢。这将换行符变成分号,man page说是必需的。

    感谢this answerread + heredoc组合。

  3. 壳牌可变

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

    注意的是,在期望命令任何'(例如,id_rsa之后)将需要与'\''替换离开单引号块中,添加一个字面撇号,然后重新输入单引号区块。 //之后的换行符与之前的选项相同。

+0

感谢您的帮助,我使用了示例1并且它工作正常。我很感激。 –