我想从另一台远程主机上执行远程主机上的命令。
HOST1=host1.domain.tld
HOST2=host2.domain.tld
HOST1
用于连接HOST2
,命令在HOST2
上执行。远程命令取决于在HOST2
上计算的变量。
ssh -A $HOST1 -C "x=wrong; ssh -A $HOST2 -C "x=right; echo \$x""
奇怪的是,上面的命令返回$x
而下一个命令返回wrong
而不是空行。
ssh -A $HOST1 -C "x=wrong; ssh -A $HOST2 -C "echo \$x""
问题1:为什么第一个命令给我$x
?
问题2:保留双引号,如何打印right
?
答案 0 :(得分:0)
...正是提出的问题。
$x
?请记住,此命令会多次执行,因此会被多个shell转换。该转换看起来类似于以下(假设{1.1}的HOST1
和2.2.2.2的HOST2
:
ssh -A 1.1.1.1 -C "x=wrong; ssh -A 2.2.2.2. -C "x=right; echo \$x""
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^
...注意箭头?这些显示了您的引用区域的开始和结束位置:x=right
之前的引用结束了x=wrong
之前开始的引用!
因此,这标记为两个单独的命令,每行写下一个shell字:
# command one: ssh
ssh \
-A \
1.1.1.1 \
-C \
"x=wrong; ssh -A 2.2.2.2. -C "x=right;
# command two: echo
echo \
\$x""
right
?反斜杠 - 转义嵌套引号,以便它们不会关闭您想要在外部引用的引号。
ssh -A $HOST1 -C "x=wrong; ssh -A $HOST2 -C \"x=right; echo \$x\""
在实践中,根本不要进行这种明确的嵌套SSH调用 - 只需使用ProxyCommand
ssh配置选项:
ssh \
-o "ProxyCommand ssh $HOST1 netcat -w 120 %h %p' \
"$HOST2" 'x=right; echo "$x"'
一般来说,试图用手逃避事情比告诉shell为你做事更容易出错。
host2_cmd='x=right; echo "$x"'
printf -v host1_cmd '%q ' ssh -A "$HOST2" -C "$host2_cmd"
ssh "$HOST1" bash -s <<<"$host1_cmd"
为了证明,我们甚至可以通过第三个主机来做到这一点:
host3_cmd='x=right; echo "$x"'
printf -v host2_cmd '%q ' ssh -A "$HOST3" -C "$host3_cmd"
printf -v host1_cmd '%q ' ssh -A "$HOST2" -C "$host2_cmd"
ssh "$HOST1" bash -s <<<"$host1_cmd"
这是有效的,因为在ksh和bash中,printf %q
引用一个字符串,以便在被同一个shell解析时评估其当前内容。