我有以下脚本:
#!/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"
我不知道它是什么意思,也不知道为什么它不起作用。但是,当我使用非嵌入式 Expect 脚本编写上述代码时:
#!/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 使用 scp
或 ssh
的问题时,给出的答案是使用 RSA 键。我尝试过,不幸的是,在我的一台计算机上,GNOME key 环存在一些糟糕的错误,这意味着我无法从 RSA key 中删除我的密码,这正是我尝试使用 if
语句编写上述脚本的原因.所以请不要告诉我使用 RSA key 。
最佳答案
您的 Bash 脚本正在 expect
的标准输入上传递 Expect 命令.那就是here-document <<EOD
做。然而,expect
...期望其命令在文件中提供,或作为 -c
的参数提供, 根据 man page .下面是三个选项。买者自负;没有经过测试。
Process substitution使用此处文档:
expect <(cat <<'EOD' spawn ... (your script here) EOD )
EOD
结束 here-document,然后整个文件被包裹在<( )
中进程替换 block 。结果是expect
将看到一个临时文件名,其中包含您此处文档的内容。正如@Aserre 指出的那样,
<<'EOD'
中的引号意味着您此处文档中的所有内容都将按字面意思处理。将它们保留下来以在脚本中扩展 Bash 变量等,如果这是您想要的。编辑变量+此处-文档:
IFS= read -r -d '' expect_commands <<'EOD' spawn ... (your script here) interact EOD expect -c "${expect_commands// /;}"
是的,
//
之后是一个真正的换行符- 对我来说如何逃避它并不明显。这会将换行符变成分号,即 man page说是必需的。感谢this answer对于
read
+heredoc 组合。外壳变量
expect_commands=' spawn ... (your script here) interact' expect -c "${expect_commands// /;}"
注意任何
'
在 expect 命令中(例如,在id_rsa
之后)将需要替换为'\''
离开单引号 block ,添加文字撇号,然后重新输入单引号 block 。//
之后的换行符与前面的选项相同。
关于bash - 在 Bash 脚本中嵌入 Expect 脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41165719/