在 bash 脚本中,我有一个 except 段,它通过 ssh 将命令发送到机器。我有
bash -c
,因为我需要在此命令中设置环境变量。
但我收到错误:
extra characters after close-quote
while executing
"spawn -noecho ssh -t anon@machine 'bash -c "cd /tmp;"'
"
当我手动运行该命令时
ssh -t anon@machine 'bash -c "cd /tmp;"'
它工作正常。这里出了什么问题?
ssh_param="-t ${scp_user}${_machine} 'bash -c \"cd /tmp;\"'"
/usr/bin/expect <<-EOF1
set timeout 360
spawn -noecho ssh ${ssh_param}
expect {
"password:" {
send "${_pass}\r"
}
eof { exit }
}
expect {
eof { exit }
}
EOF1
另外,如果我将 ssh_param 设置为
ssh_param="-t ${scp_user}${_machine} \"cd /tmp;\""
这有效,那么为什么 bash -c ...
会导致它失败?
bash 在定界文档上进行参数替换后,
expect
运行于
set timeout 360
spawn -noecho ssh -t XXXYYY 'bash -c "cd /tmp;"'
expect {
"password:" {
send "ZZZ\r"
}
eof { exit }
}
expect {
eof { exit }
}
expect
脚本是用 tcl
语言编写的,其基本工作原理是将一行分成单词,并将第一个单词视为命令,在进行替换后将其余单词作为参数运行。有点像 shell 那样,但有更合理的规则。用于解析 tcl 的 12 条规则 称为 Dodekalogue。
单引号不用于将多个单词组合成一个 - 仅使用双引号、
[]
(表示要评估的命令和参数)和{}
(不替换或评估其中的任何内容)。所以这条线
spawn -noecho ssh -t XXXYYY 'bash -c "cd /tmp;"'
分为
spawn
、-noecho
、ssh
、-t
、XXXYYY
、'bash
、-c
和 "cd /tmp;"'
。最后一个单词的右双引号后面的单引号是错误的。通常在 tcl 中,您只需将其括在大括号中(或双引号,但随后您必须转义嵌套的引号):
spawn -noecho ssh -t XXXYYY {bash -c "cd /tmp;"}
这意味着您设置的 shell 变量需要类似于
ssh_param="-t ${scp_user}${_machine} {bash -c \"cd /tmp;\"}"
在 tcl/expect 中编写整个内容,而不是构建期望脚本执行的 shell 将使生活更轻松,因为您不必在不同的引用样式之间切换,担心 shell 参数扩展导致生成无效的 tcl,如本例所示等等