在 Bash 脚本中嵌入 Expect 脚本
Embedding an Expect script inside a Bash script
我有以下脚本:
#!/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 密钥环存在一些糟糕的错误,这意味着我无法从 RSA 密钥中删除我的密码,这正是我尝试使用 [= 编写上述脚本的原因16=] 语句。所以请不要告诉我使用 RSA 密钥。
您的 Bash 脚本正在 expect
的标准输入上传递 Expect 命令。那就是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。下面是三个选项。买者自负; none 已测试。
Process substitution 此处文档:
expect <(cat <<'EOD'
spawn ... (your script here)
EOD
)
EOD
结束 here-document,然后整个内容被包裹在 <( )
进程替换块中。结果是 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 组合。
Shell变量
expect_commands='
spawn ... (your script here)
interact'
expect -c "${expect_commands//
/;}"
请注意,expect 命令中的任何 '
(例如,在 id_rsa
之后)都需要替换为 '\''
以离开单引号块,添加文字撇号, 然后重新输入单引号块。 //
后的换行符与前面的选项相同。
我有以下脚本:
#!/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 密钥环存在一些糟糕的错误,这意味着我无法从 RSA 密钥中删除我的密码,这正是我尝试使用 [= 编写上述脚本的原因16=] 语句。所以请不要告诉我使用 RSA 密钥。
您的 Bash 脚本正在 expect
的标准输入上传递 Expect 命令。那就是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。下面是三个选项。买者自负; none 已测试。
Process substitution 此处文档:
expect <(cat <<'EOD' spawn ... (your script here) EOD )
EOD
结束 here-document,然后整个内容被包裹在<( )
进程替换块中。结果是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 组合。Shell变量
expect_commands=' spawn ... (your script here) interact' expect -c "${expect_commands// /;}"
请注意,expect 命令中的任何
'
(例如,在id_rsa
之后)都需要替换为'\''
以离开单引号块,添加文字撇号, 然后重新输入单引号块。//
后的换行符与前面的选项相同。