在Bash脚本中嵌入Expect脚本 [英] Embedding an Expect script inside a Bash script

查看:382
本文介绍了在Bash脚本中嵌入Expect脚本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下脚本:

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

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

Unfortunately it doesn't seem to work and I get an error message:

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"

我不知道这意味着什么,为什么不起作用.但是,当我使用未嵌入的Expect脚本编写以上代码时:

I don't know what it means and why it doesn't work. However, when I wrote the above code using a not-embedded Expect script:

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

它正常工作没有任何问题.那我在做什么错了?

It worked without any problems. So what am I doing wrong?

注意:通常,当有人发布有关使用Expect使用scpssh的问题时,给出的答案是使用

NOTE: Often when someone posts a question about using Expect to use scp or ssh the answer given is to use RSA keys. I tried, unfortunately on one of my computers there is some crappy bug with the GNOME keyring that means that I can't remove my password from the RSA key, which is exactly why I'm trying to write the above script with an if statement. So please don't tell me to use RSA keys.

推荐答案

您的Bash脚本在expect的标准输入上传递了Expect命令.这就是此处文档 <<EOD做.但是,根据

Your Bash script is passing the Expect commands on the standard input of expect. That is what the here-document <<EOD does. However, expect... expects its commands to be provided in a file, or as the argument of a -c, per the man page. Three options are below. Caveat emptor; none have been tested.

  1. 使用此处文档替换:

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

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

The EOD ends the here-document, and then the whole thing is wrapped in a <( ) process substitution block. The result is that expect will see a temporary filename including the contents of your here-document.

正如@Aserre所指出的那样,<<'EOD'中的引号表示此处文档中的所有内容都将按字面意义处理.如果需要的话,请不要使用它们来扩展脚本中的Bash变量等.

As @Aserre noted, the quotes in <<'EOD' mean that everything in your here-document will be treated literally. Leave them off to expand Bash variables and the like inside the script, if that's what you want.

编辑变量+此处文档:

IFS= read -r -d '' expect_commands <<'EOD'
spawn ... (your script here)
interact
EOD

expect -c "${expect_commands//
/;}"

是的,这是//之后的真正换行符-对我来说,如何转义它并不明显.这就把换行符变成了分号,手册页上是必需的.

Yes, that is a real newline after // - it's not obvious to me how to escape it. That turns newlines into semicolons, which the man page says is required.

感谢此答案,用于read + heredoc组合.

Thanks to this answer for the read+heredoc combo.

Shell变量

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

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

Note that any ' in the expect commands (e.g., after id_rsa) will need to be replaced with '\'' to leave the single-quote block, add a literal apostrophe, and then re-enter the single-quote block. The newline after // is the same as in the previous option.

这篇关于在Bash脚本中嵌入Expect脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆